2 efaxlib.c - utility routines for efax
3 Copyright 1995 Ed Casas
19 #define DEFXRES 204.145 /* fax x and y resolution in dpi */
20 #define DEFYRES 195.58
22 #define DEFWIDTH 1728 /* 215x297 mm image at fax resolution */
23 #define DEFHEIGHT 2287
25 extern t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] ; /* T.4 coding tables */
26 extern t4tab btab [ ( 64 + 27 + 13 ) + 1 ] ;
29 short short256 = 256 ; /* for endian-ness detection */
31 /* Make sure printf strings have only %d escapes and n or fewer
32 of them. Returns 0 if OK, 1 on error. */
34 int ckfmt ( char *p, int n )
38 if ( p[1] == 'd' ) n-- ;
39 else if ( p[1] == '%' ) p++ ;
49 /* Initialize state of variable-length code word encoder. */
51 void newENCODER ( ENCODER *e )
58 /* Store a code word `code' of length `bits' (<=24) in buffer pointed to by
59 `buf'. Bits that don't fit in complete bytes are saved between calls.
60 To flush the remaining bits call the function with code=0 and bits=0.
61 Returns pointer to next free element in output buffer. Calling function
62 must ensure at least bits/8 bytes are available in buffer. */
64 uchar *putcode ( ENCODER *e, short code, short bits, uchar *buf )
66 e->x = ( e->x << bits ) | code ;
67 e->shift += bits ? bits : -e->shift ;
69 while ( e->shift >= 0 ) {
70 *buf++ = e->x >> e->shift ;
78 /* Convert run lengths to 1-D T.4-codes. First run is white. Silently
79 truncates run lengths that are too long. After using this function EOLs
80 may need to be added and/or the putcode() buffer flushed. Returns
81 pointer to next free element in output buffer. */
83 uchar *runtocode ( ENCODER *e, short *runs, int nr, uchar *codes )
85 uchar col = 0, *maxcodes = codes + MAXCODES ;
86 t4tab *ctab = wtab, *p ;
91 #define PUTCODE(p) { x = ( x << p->bits ) | p->code ; shift += p->bits ; \
92 while ( shift >= 0 ) { *codes++ = x >> shift ; shift -= 8 ; } }
94 x = e->x ; shift = e->shift ;
98 if ( rlen > 63 ) { /* make-up code */
99 if ( rlen > MAXRUNLEN ) rlen = MAXRUNLEN ;
100 p = ctab + 63 + ( rlen >> 6 ) ;
101 if ( codes < maxcodes ) PUTCODE(p) ;
103 p = ctab + ( rlen & 0x3f ) ; /* terminating code */
104 if ( codes < maxcodes ) PUTCODE(p) ;
105 ctab = ( col ^= 1 ) ? btab : wtab ;
108 e->x = x ; e->shift = shift ;
114 /* Pad/truncate run-length coded scan line 'runs' of 'nr' runs by 'pad'
115 pixels (truncate if negative). Returns the new number of runs. */
117 int xpad ( short *runs, int nr, int pad )
119 if ( pad < 0 ) { /* truncate */
120 while ( pad < 0 ) pad += ( nr <= 0 ? -pad : runs [ --nr ] ) ;
121 runs [ nr++ ] = pad ;
122 } else { /* pad with white */
123 if ( nr & 1 ) runs [ nr - 1 ] += pad ;
124 else runs [ nr++ ] = pad ;
130 /* Shift a run-length coded scan line right by s pixels (left if negative).
131 If necessary, zero-length runs are created to avoid copying. Returns
132 the pixel width change (+/-). */
135 int xshift ( short *runs, int nr, int s )
139 for ( i = 0 ; s < 0 && i < nr ; i++ ) {
154 /* Scale nr run lengths in buffer pointed to by p to scale image
155 horizontally. The scaling factor is xs/256. Returns new line width in
158 int xscale ( short *p, int nr, int xs )
160 int inlen=0, outlen=0 ;
161 for ( ; nr-- > 0 ; p++ ) {
163 *p = ( ( inlen * xs + 128 ) >> 8 ) - outlen ;
171 /* Zero-terminated lists of run lengths for each byte. */
173 static uchar byteruns [ 1408 + 1 ] =
174 "8071061106205120511105210530413041210411110411204220421104310440"
175 "3140313103121103122031112031111103112103113032303221032111032120"
176 "3320331103410350215021410213110213202121202121110212210212302111"
177 "3021112102111111021111202112202112110211310211402240223102221102"
178 "2220221120221111022121022130233023210231110231202420241102510260"
179 "1160115101141101142011312011311101132101133011213011212101121111"
180 "0112112011222011221101123101124011114011113101111211011112201111"
181 "1120111111110111112101111130111230111221011121110111212011132011"
182 "1311011141011150125012410123110123201221201221110122210122301211"
183 "3012112101211111012111201212201212110121310121401340133101321101"
184 "3220131120131111013121013130143014210141110141201520151101610170"
185 "1701610151101520141201411101421014301313013121013111101311201322"
186 "0132110133101340121401213101212110121220121112012111110121121012"
187 "1130122301222101221110122120123201231101241012501115011141011131"
188 "1011132011121201112111011122101112301111130111112101111111101111"
189 "1120111122011112110111131011114011240112310112211011222011211201"
190 "1211110112121011213011330113210113111011312011420114110115101160"
191 "2602510241102420231202311102321023302213022121022111102211202222"
192 "0222110223102240211402113102112110211220211112021111110211121021"
193 "1130212302122102121110212120213202131102141021503503410331103320"
194 "3212032111032210323031130311210311111031112031220312110313103140"
195 "4404310421104220411204111104121041305305210511105120620611071080" ;
197 /* Convert byte-aligned bit-mapped n-byte scan line into array of run
198 lengths. Run length array must have *more* than 8*n elements. First
199 run is white. Returns number of runs coded. */
201 static int bittorun ( uchar *bits, int n, short *runs )
203 static uchar init=0, *rltab [ 256 ] ;
204 register uchar *p, c, lastc = 0x00 ;
205 short *runs0 = runs ;
207 if ( ! init ) { /* initialize pointer and run tables */
209 for ( rltab[ 0 ] = p = byteruns ; *p ; p++ )
210 if ( ! ( *p -= '0' ) && i < 255 )
211 rltab [ ++i ] = p+1 ;
216 for ( ; n > 0 ; n-- ) {
217 p = rltab [ c = *bits++ ] ;
218 if ( ( lastc & 0x01 ) ? ! ( c & 0x80 ) : ( c & 0x80 ) )
219 *(++runs) = *p++ ; /* new run */
221 *runs += *p++ ; /* continue run */
227 return runs - runs0 + 1 ;
231 /* Bitwise-OR two run-length coded scan lines. The run length
232 vectors a and b are OR-ed into c. If c is null, the result is
233 placed in a. The new image width is stored in pels if it is
234 not null. Returns the number of runs in the result. */
236 int runor ( short *a, int na, short *b, int nb, short *c, int *pels )
238 register short la, lb ;
239 int ia, ib, ic, np=0 ;
240 short tmp [ MAXRUNS ] ;
249 if ( la <= lb ) { /* select shorter sub-run */
250 if ( ( ( ia | ib ) ^ ic ) & 1 ) /* OR of subruns same colour as c? */
251 c [ ++ic ] = la ; /* no, new output run */
253 c [ ic ] += la ; /* yes, add it */
254 lb -= la ; /* align subruns */
255 if ( ++ia >= na ) break ; /* done */
256 la = a [ ia ] ; /* get new subrun */
257 } else { /* same for line b ... */
258 if ( ( ( ia | ib ) ^ ic ) & 1 )
263 if ( ++ib >= nb ) break ;
270 if ( ( ia ^ ic ) & 1 )
274 if ( ++ia >= na ) break ;
279 if ( ( ib ^ ic ) & 1 )
283 if ( ++ib >= nb ) break ;
287 if ( c == tmp ) for ( ia=0 ; ia <= ic ; ia++ ) np += a[ia] = c[ia] ;
289 if ( pels ) *pels = np ;
295 /* Get a number from a PBM file header while skipping whitespace
296 and comments. Returns the number or 0 on EOF. Reads one more
297 byte than used by the number. */
299 static int pbmdim ( IFILE *f )
303 /* scan for first digit and skip comments */
304 while ( ! isdigit ( c = fgetc ( f->f ) ) && c >= 0 )
306 while ( ( c = fgetc ( f->f ) ) != '\n' && c >= 0 ) ;
309 if ( c >= 0 && isdigit( c ) ) {
311 while ( isdigit ( c = fgetc ( f->f ) ) && c >= 0 )
312 n = n * 10 + c - '0' ;
319 /* Append nb bits from in[from] to bit-mapped scan line buffer
320 where `from' is a bit (not byte) index. Bits in bytes are
321 ordered from MS to LS bit. Initialize before each scan line by
322 calling with nb=0 and in pointing to output buffer. Flush
323 after each scan line by calling with nb=0 and in=NULL. */
325 #define putbits( c, b ) { x = ( x << (b) ) | (c) ; shift += (b) ; \
326 if ( shift >= 0 ) { *out++ = x >> shift ; shift -= 8 ; } }
329 void copybits ( uchar *in, int from, short nb )
334 static short x, shift ;
335 static unsigned char right [ 9 ] = {
336 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff } ;
338 if ( ! nb ) { /* reset for new scan line */
340 else putbits ( 0, -shift ) ; /* or flush bit buffer */
344 f = in + ( from >> 3 ) ;
345 bits = 8 - ( from & 7 ) ;
348 putbits ( *f++ & right [ bits ], bits ) ;
351 putbits ( ( *f >> ( bits - nb ) ) & right [ bits ], nb ) ;
355 while ( nb >= 8 ) { putbits ( *f++, 8 ) ; nb -= 8 ; }
357 if ( nb > 0 ) putbits ( *f >> ( 8 - nb ), nb );
363 /* Generate scan line 'line' of string 'txt' using font `font'
364 and store the runs in 'runs'. The font is scaled so it
365 appears to have cells of width w and height h. lmargin pixels
366 of white space are added at the left margin. Sets 'pels' to
367 line width if not null. Returns number of runs coded. */
370 int texttorun ( uchar *txt, faxfont *font, short line,
371 int w, int h, int lmargin,
372 short *runs, int *ppels )
374 uchar *in, out [ MAXLINELEN * MAXFONTW / 8 + 1 ] ;
375 int i, nc = 0, cw, nr, pels ;
377 line = ( line * font->h + h/2 ) / h ;
380 if ( line >= font->h ) line = font->h - 1 ;
381 in = font->buf + 256/8 * cw * line ;
383 copybits ( out, 0, 0 ) ;
384 for ( i=0 ; txt[i] && i < MAXLINELEN ; i++ ) {
385 copybits ( in, font->offset [ txt[i] ], cw ) ;
387 while ( ( txt[i] == HT ) && ( nc & 7 ) ) { /* tab */
388 copybits ( in, font->offset [ ' ' ], cw ) ;
392 copybits ( 0, 0, 0 ) ;
394 nr = bittorun ( out, ( nc*cw + 7 )/8, runs ) ;
399 pels = xscale ( runs, nr, ( w * 256 ) / font->w ) ;
401 pels += xshift ( runs, nr, lmargin ) ;
403 if ( ppels ) *ppels = pels ;
409 /* Image File Input Functions */
412 /* Names of file formats */
414 static char *iformatname [ NIFORMATS ] = IFORMATS ;
416 static char *oformatname [ NOFORMATS ] = OFORMATS ;
418 static char *pformatname [ NPFORMATS ] = PFORMATS ;
420 /* Log the names of files still to be sent using the "msg()"
423 void logifnames ( IFILE *f, char *s )
429 for ( p = f->page ; p <= f->lastpage ; p++ ) {
431 if ( fn ) msg ( s, fn ) ;
436 /* Bit reversal lookup tables (note that the `normalbits' array
437 is the one actually used for the bit reversal. */
439 uchar reversebits [ 256 ], normalbits [ 256 ] ;
441 /* Read run lengths for one scan line from T.4-coded IFILE f into buffer
442 runs. If pointer pels is not null it is used to save pixel count.
443 Returns number of runs stored, EOF on RTC, or -2 on EOF or other
447 int readruns ( IFILE *f, short *runs, int *pels )
449 int err=0, c=EOF, n ;
453 short *p, *maxp, *q, len=0, npad=0 ;
455 uchar reverse=f->page->revbits ;
457 maxp = ( p = runs ) + MAXRUNS ;
460 x = d->x ; shift = d->shift ; tab = d->tab ; /* restore decoder state */
464 while ( shift < 0 ) {
465 if ( ( c = fgetc ( f->f ) ) == EOF ) {
466 x = ( x << 15 ) | 1 ; shift += 15 ; /* EOL pad at EOF */
469 if ( reverse ) c = normalbits [ c & 0xff ] ;
470 x = ( x << 8 ) | c ; shift += 8 ;
473 t = tab + ( ( x >> shift ) & 0x1ff ) ;
476 } while ( ! t->code ) ;
477 if ( p < maxp ) *p++ = t->code ;
478 } while ( t->code != -1 ) ;
480 d->x = x ; d->shift = shift ; d->tab = tab ; /* save state */
482 if ( npad > 1 ) msg ("W EOF before RTC" ) ;
484 if ( p >= maxp ) msg ( "W run length buffer overflow" ) ;
486 /* combine make-up and terminating codes and remove +1 offset
490 for ( p = q = runs ; n-- > 0 ; )
491 if ( *p > 64 && n-- > 0 ) {
492 len += *q++ = p[0] + p[1] - 2 ;
495 len += *q++ = *p++ - 1 ;
499 /* check for RTC and errors */
504 if ( ++(d->eolcnt) >= RTCEOL ) err = EOF ;
507 if ( ferror ( f->f ) ) {
508 err = -msg ("ES2error reading fax file:") ;
514 if ( pels ) *pels = len ;
516 return err ? err : n ;
521 /* Read a PCX compressed bit-map */
524 int readpcx ( char *p, int len, IFILE *f )
528 while ( !err && len > 0 ) {
529 if ( ( c = fgetc ( f->f ) ) < 0 ) {
530 err = msg ( "ES2 PCX read failed" ) ;
532 if ( ( c & 0xc0 ) == 0xc0 ) { /* a run count */
535 if ( ( c = fgetc ( f->f ) ) < 0 ) {
536 err = msg ( "ES2 PCX read failed" ) ;
538 memset ( p, c, n <= len ? n : len ) ;
542 } else { /* bits 0 to 7 are image data */
550 msg ( "W PCX run-length coding error" ) ;
556 /* Read a scan line from the current page of IFILE f. Stores
557 number of runs in runs and line width in pels if not null.
558 Pages ends at EOF. Text pages also end if a complete text line
559 would not fit or if the line contains a formfeed character.
560 PBM pages also end when all lines in the bitmap have been
561 read. Fax pages also end at RTC. Returns number of runs stored
562 or EOF at end of page. */
564 int readline ( IFILE *f, short *runs, int *pels )
570 uchar bits [ MAXBITS ] ;
572 if ( f->lines != 0 ) { /* -1 allowed as well */
573 switch ( f->page->format ) {
577 if ( f->txtlines <= 0 ) { /* need another text line */
578 if ( fgets ( f->text, MAXLINELEN, f->f ) ) {
579 f->txtlines = f->charh ;
580 if ( strchr ( f->text, FF ) ) {
581 f->lines = 0 ; /* no more lines in this page */
582 nr = EOF ; /* don't return any */
589 nr = texttorun ( (uchar*) f->text, f->font, f->charh - f->txtlines,
590 f->charw, f->charh, f->lmargin,
599 if ( fread ( bits, 1, f->page->w/8, f->f ) != f->page->w/8 ) {
602 nr = bittorun ( bits, f->page->w/8, runs ) ;
603 if ( pels ) *pels = f->page->w ;
609 nr = readruns ( f, runs, pels ) ;
613 nb = ( ( f->page->w + 15 ) / 16 ) * 2 ; /* round up */
614 if ( readpcx ( bits, nb, f ) != 0 ) {
617 nr = bittorun ( bits, nb, runs ) ;
618 if ( pels ) *pels = f->page->w ;
628 if ( nr >= 0 && f->lines > 0 ) f->lines-- ;
634 /* Deduce the file type by scanning buffer p of n bytes. */
636 static int getformat ( uchar *p, int n )
640 /* figure out file type if not already set */
643 if ( ! format && n < 2 ) {
645 msg ( "W only read %d byte(s) from input file, assuming text", n ) ;
648 if ( ! format && ! p[0] && ! ( p[1] & 0xe0 ) ) {
653 if ( ! format && ! strncmp ( p, "P4", 2 ) ) {
658 if ( ! format && n >= 128 && p[0] == 0x0a &&
659 strchr ("\02\03\05", p[1] ) && p[2] <= 1 ) {
661 msg ( "E can't read colour PCX" ) ;
663 format = p[2] ? I_PCX : I_PCX ;
667 if ( ! format && ! strncmp ( p, "%!", 2 ) ) {
668 msg ( "W Postscript input file will be treated as text" ) ;
671 if ( ! format && ( p[0] == 'M' || p[1] == 'I' ) && ( p[1] == p[0] ) ) {
676 ( p[0] == 0x3a && p[1] == 0xde &&
677 p[2] == 0x68 && p[3] == 0xb1) ) {
681 if ( ! format && n ) { /* "90% printable" heuristic */
683 for ( i=0 ; i<n ; i++ ) {
684 if ( isspace ( p[i] ) || isprint ( p[i] ) ) {
688 if ( ( nprint / (float) n ) > 0.90 ) {
698 /* initialize page descriptor */
700 static void page_init ( PAGE *p, char *fn )
713 static void page_report ( PAGE *p, int fmt, int n )
715 msg ( "F page %d : %s + %ld : %dx%d @ %.fx%.f dpi %s/%s",
717 p->fname, p->offset, p->w, p->h,
719 iformatname [fmt], pformatname [p->format] ) ;
722 /* File handling for undefined file types */
727 /* File handling for TIFF files */
731 /* Name of TIFF tag 'tag'. */
734 char *tagname ( int tag )
736 static struct tagnamestruct { int code ; char *name ; }
740 { 258, "bits/sample" },
741 { 259, "compresssion(g3=3)" },
742 { 262, "photometric(0-min=white)" },
743 { 266, "fill order(msb2lsb=1)" },
744 { 273, "strip offsets" },
745 { 274, "orientation(1=normal)" },
746 { 277, "samples/pixel" },
747 { 278, "rows/strip" },
748 { 279, "strip byte counts" },
749 { 282, "xresolution" },
750 { 283, "yresolution" },
751 { 284, "storage(1=single plane)" },
752 { 292, "g3options" },
753 { 296, "resolution units(2=in,3=cm)" },
754 { 297, "page number" },
755 { 327, "clean fax(0=clean/1=regen/2=errors)" },
759 for ( p=tagnames ; p->code ; p++ )
760 if ( tag == p->code ) break ;
761 return p->code ? p->name : "unknown tag" ;
764 /* Read 2- or 4-byte integers from a file and correct for file
765 endianness. Returns 0 if OK, 1 on error. */
767 int fread2 ( unsigned short *p, IFILE *f )
772 err = fread ( c, 1, 2, f->f ) == 2 ? 0 : 1 ;
775 c[0] << 8 | c[1] << 0 :
776 c[1] << 8 | c[0] << 0 ;
781 int fread4 ( unsigned long *p, IFILE *f )
786 err = fread ( c, 1, 4, f->f ) == 4 ? 0 : 1 ;
789 c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3] << 0 :
790 c[3] << 24 | c[2] << 16 | c[1] << 8 | c[0] << 0 ;
797 /* Read a TIFF directory at current file offset, save image
798 format information and seek to next directory if any. Returns
799 0 if OK, 2 on errors. */
802 int tiff_next ( IFILE *f )
805 unsigned short ntag, tag, type ;
806 unsigned long count, tv ;
809 msg ( "F+ TIFF directory at %ld", ftell ( f->f ) ) ;
811 if ( fread2 ( &ntag, f ) ) {
812 err = msg ( "E2can't read TIFF tag count" ) ;
814 msg ( "F+ with %d tags", (int) ntag ) ;
817 for ( ; ! err && ntag > 0 ; ntag-- ) {
819 err = err || fread2 ( &tag, f ) ;
820 err = err || fread2 ( &type, f ) ;
821 err = err || fread4 ( &count, f ) ;
823 if ( type == 3 ) { /* left-aligned short */
824 unsigned short a, b ;
825 err = err || fread2 ( &a, f ) ;
826 err = err || fread2 ( &b, f ) ;
828 } else { /* long or offset to data */
829 err = err || fread4 ( &tv, f ) ;
832 if ( type == 5 ) { /* float as ratio in directory data */
834 err = err || ( ( where = ftell ( f->f ) ) < 0 ) ;
835 err = err || fseek ( f->f, tv, SEEK_SET ) ;
836 err = err || fread4 ( &a, f ) ;
837 err = err || fread4 ( &b, f ) ;
838 err = err || fseek ( f->f, where, SEEK_SET ) ;
839 ftv = (float) a / ( b ? b : 1 ) ;
845 err = msg ( "ES2can't read TIFF tag" ) ;
851 char *tagtype[] = { "none", "byte", "ascii", "short", "long", "ratio" } ;
852 msg ( "F %3d %-5s tag %s %5ld (%3d:%s)",
854 type <= 5 ? tagtype[type] : "other",
855 count > 1 ? "@" : "=",
856 type == 5 ? (long) ftv : tv, tag, tagname(tag) ) ;
861 case 256 : /* width */
864 case 257 : /* height */
867 case 259 : /* compression: 1=none, 3=G3 */
869 f->page->format = P_RAW ;
870 } else if ( tv == 3 ) {
871 f->page->format = P_FAX ;
873 err = msg ( "E2can only read TIFF/G3 or TIFF/uncompressed" ) ;
876 case 266 : /* fill order */
877 f->page->revbits = ( tv == 2 ? 1 : 0 ) ;
879 case 273 : /* data offset */
881 err = msg ( "E2can't read multi-strip TIFF files" ) ;
883 f->page->offset = tv ;
885 case 282 : /* x resolution */
886 f->page->xres = ftv ;
888 case 283 : /* y resolution */
889 f->page->yres = ftv ;
891 case 292 : /* T4 options: 1=2D, 2=uncompressed */
893 err = msg ( "E2can't read 2D compressed TIFF-F file" ) ;
895 err = msg ( "E2can't read uncompressed TIFF-F file" ) ;
897 case 296 : /* units: 2=in, 3=cm */
899 f->page->xres *= 2.54 ;
900 f->page->yres *= 2.54 ;
905 } /* end of tag reading loop */
908 if ( f->page->format == I_AUTO ) {
909 msg ( "W missing TIFF compression format, set to raw" ) ;
910 f->page->format = P_RAW ;
915 if ( fread4 ( &(f->next), f ) ) {
916 err = msg ( "E2can't read offset to next TIFF directory" ) ;
919 msg ( "F , next directory at %ld.", f->next ) ;
920 if ( fseek ( f->f, f->next, SEEK_SET ) )
921 err = msg ( "ES2 seek to next TIFF directory failed" ) ;
923 msg ( "F , last image." ) ;
929 if ( ! f->page->offset )
930 err = msg ( "E2 missing offset to TIFF data" ) ;
936 int tiff_first ( IFILE *f )
938 short magic, version ;
940 fread ( (uchar*) &magic, 1, 2, f->f ) ;
941 f->bigend = ( *(uchar*) &magic == 'M' ) ? 1 : 0 ;
942 fread2 ( &version, f ) ;
943 fread4 ( &(f->next), f ) ;
945 msg ( "F TIFF version %d.%d file (%s-endian)",
946 version/10, version%10, f->bigend ? "big" : "little" ) ;
948 fseek ( f->f, f->next, SEEK_SET ) ;
950 return tiff_next ( f ) ;
954 /* File handling for text files. */
956 int text_next ( IFILE *f )
959 char buf [ MAXLINELEN ] ;
961 f->page->offset = ftell ( f->f ) ;
962 f->page->format = P_TEXT ;
964 nc = ( f->page->w - f->lmargin ) / f->charw ;
966 if ( nc > MAXLINELEN )
969 for ( i = 0 ; i < f->pglines && fgets ( buf, nc, f->f ) ; i++ ) ;
971 f->next = ! feof(f->f) ? ftell ( f->f ) : 0 ;
973 err = ferror(f->f) ? 2 : 0 ;
979 int text_first ( IFILE *f )
981 static faxfont defaultfont ;
984 /* use default font scaled 2X, 1 inch margin, 66 lines/page */
985 f->font = &defaultfont ;
986 readfont ( 0, f->font ) ;
987 if ( ! f->charw ) f->charw = 2 * f->font->w ;
988 if ( ! f->charh ) f->charh = 2 * f->font->h ;
989 if ( ! f->lmargin ) f->lmargin = 204 ;
990 if ( ! f->pglines ) f->pglines = DEFPGLINES ;
992 /* if not set, take default values from font */
993 if ( ! f->charw ) f->charw = f->font->w ;
994 if ( ! f->charh ) f->charh = f->font->h ;
995 if ( ! f->lmargin ) f->lmargin = 0 ;
996 if ( ! f->pglines ) f->pglines = f->page->h / f->charh - 6 ;
998 return text_next ( f ) ;
1000 #endif /* UCLINUX */
1003 /* File handling for PBM files */
1005 static int pbm_first ( IFILE *f )
1009 fseek ( f->f, 2, SEEK_SET ) ;
1011 if ( ! ( f->page->w = pbmdim ( f ) ) || ! ( f->page->h = pbmdim ( f ) ) ) {
1012 err = msg ( "E2 EOF or 0 dimension in PBM header" ) ;
1013 } else if ( f->page->w % 8 ) {
1014 err = msg ( "E2 PBM width must be multiple of 8" ) ;
1016 msg ( "F read %dx%d PBM header", f->page->w, f->page->h ) ;
1019 f->page->offset = ftell ( f->f ) ;
1020 f->page->format = P_PBM ;
1029 /* File handling for FAX files */
1035 /* File handling for PCX files */
1037 /* get a 16-bit word in Intel byte order. */
1040 int fgeti ( IFILE *f )
1042 return fgetc ( f->f ) + fgetc ( f->f ) * 256 ;
1045 int pcx_first ( IFILE *f )
1047 int err=0, xmin, xmax, ymin, ymax, nc, nb ;
1050 start = ftell ( f->f ) ;
1052 fseek ( f->f, start+4, SEEK_SET ) ;
1053 xmin = fgeti ( f ) ;
1054 ymin = fgeti ( f ) ;
1055 xmax = fgeti ( f ) ;
1056 ymax = fgeti ( f ) ;
1058 f->page->w = xmax - xmin + 1 ;
1059 f->page->h = ymax - ymin + 1 ;
1061 f->page->xres = fgeti ( f ) ;
1062 f->page->yres = fgeti ( f ) ;
1064 fseek ( f->f, start+0x41, SEEK_SET ) ;
1065 nc = fgetc ( f->f ) ;
1069 msg ( "W mono PCX file has %d colour planes", nc ) ;
1071 if ( nb != ( f->page->w + 15 ) / 16 * 2 )
1072 msg ( "W PCX file has %d bytes per scan line for %d pels",
1075 f->page->offset = start + 128 ;
1076 f->page->format = P_PCX ;
1083 /* File handling for DCX files */
1085 int dcx_next ( IFILE *f )
1090 /* get this and next pages' offsets */
1092 fseek ( f->f, f->next, SEEK_SET ) ;
1093 fread4 ( &thisp, f ) ;
1094 fread4 ( &nextp, f ) ;
1096 /* save address of next directory entry, if any */
1098 f->next = nextp ? f->next + 4 : 0 ;
1101 err = msg ( "E2 can't happen (dcx_next)" ) ;
1103 fseek ( f->f, thisp, SEEK_SET ) ;
1105 return err ? err : pcx_first ( f ) ;
1108 int dcx_first ( IFILE *f )
1112 return dcx_next ( f ) ;
1121 /* input file state reset for different compression methods */
1124 #endif /* UCLINUX */
1128 int text_reset ( IFILE *f )
1132 f->lines = ( ( f->pglines * f->charh ) / f->charh ) * f->charh ;
1134 f->page->yres = f->lines > 1078 ? 196 : 98 ; /* BOGUS */
1139 int fax_reset ( IFILE *f )
1142 short runs [ MAXRUNS ] ;
1144 newDECODER ( &f->d ) ;
1145 if ( readruns ( f, runs, &pels ) < 0 || pels ) /* skip first EOL */
1146 msg ( "W first line has %d pixels: probably not fax data", pels ) ;
1151 #endif /* UCLINUX */
1154 /* Skip to start of same (dp=0) or next (dp=1) page image.
1155 Returns 0 if OK, 1 if no more pages, 2 on errors. */
1157 int nextipage ( IFILE *f, int dp )
1161 int ( *reset [NPFORMATS] ) ( IFILE * ) = {
1163 raw_reset, fax_reset,
1164 #endif /* UCLINUX */
1167 text_reset, pcx_reset
1168 #endif /* UCLINUX */
1171 /* close current file if any and set to NULL */
1178 /* if requested, point to next page and check if done */
1184 if ( f->page > f->lastpage ) {
1188 /* open the file and seek to start of image data */
1191 f->f = fopen ( f->page->fname, (f->page->format == P_TEXT) ? "r" : "rb" ) ;
1193 err = msg ( "ES2can't open %s:", f->page->fname ) ;
1196 if ( ! err && fseek ( f->f, f->page->offset, SEEK_SET ) )
1197 err = msg ( "ES2 seek failed" ) ;
1199 /* default initializations */
1201 f->lines = f->page->h ;
1203 /* coding-specific initializations for this page */
1206 pf = reset[f->page->format] ;
1215 /* Returns true if on last file. */
1217 int lastpage ( IFILE *f )
1219 return f->page >= f->lastpage ;
1222 #define dfax_first 0
1225 /* Initialize an input (IFILE) structure. This structure
1226 collects the data about images to be processed to allow a
1227 simple interface for functions that need to read image files.
1229 The IFILE is initialized by building an array of information
1230 for each page (image) in all of the files.
1232 The page pointer index is initialized so that the first call
1233 to nextipage with dp=1 actually opens the first file.
1238 int newIFILE ( IFILE *f, char **fnames )
1240 int err=0, i, n = 0 /* GCC paranoia */, fformat=0 ;
1243 int ( *fun ) ( IFILE * ) ;
1245 int ( *first [NIFORMATS] ) ( IFILE * ) = {
1246 auto_first, pbm_first,
1248 fax_first, text_first, tiff_first,
1249 dfax_first, pcx_first, raw_first, dcx_first
1250 #endif /* UCLINUX */
1253 int ( *next [NIFORMATS] ) ( IFILE * ) = {
1254 auto_next, pbm_next,
1256 fax_next, text_next, tiff_next,
1257 dfax_next, pcx_next, raw_next, dcx_next
1258 #endif /* UCLINUX */
1261 f->page = f->pages ;
1263 /* get info for all pages in all files */
1265 for ( p=fnames ; ! err && *p ; p++ ) {
1267 if ( ! ( f->f = fopen ( *p, "rb" ) ) )
1268 err = msg ( "ES2 can't open %s:", *p ) ;
1271 n = fread ( buf, 1, 128, f->f ) ;
1272 if ( ferror ( f->f ) )
1273 err = msg ( "ES2 can't open %s:", *p ) ;
1277 fformat = getformat ( buf, n ) ;
1279 err = msg ( "E2 can't get format of %s", *p ) ;
1282 if ( ! err && fseek ( f->f, 0, SEEK_SET ) )
1283 err = msg ( "ES2 can't rewind %s:", *p ) ;
1285 /* get format information for all pages in this file */
1287 for ( i=0 ; ! err ; i++ ) {
1289 page_init ( f->page, *p ) ;
1291 if ( ( fun = i ? next[fformat] : first[fformat] ) )
1296 page_report ( f->page, fformat, f->page - f->pages + 1 ) ;
1300 if ( f->page >= f->pages + MAXPAGE )
1301 err = msg ( "E2 too many pages (max is %d)", MAXPAGE ) ;
1304 if ( ! f->next ) break ;
1314 f->lastpage = f->page - 1 ;
1316 f->page = f->pages ;
1318 if ( ! normalbits[1] ) initbittab() ; /* bit-reverse table initialization */
1323 /* Image File Output Functions */
1325 /* Strings and function to write a bit map in HP-PCL format. The only
1326 compression is removal of trailing zeroes. Margins and resolution are
1327 set before first write. */
1331 "\033E" /* Printer reset. */
1332 "\033&l0E" /* top margin = 0 */
1333 "\033&a0L" /* left margin = 0 */
1334 "\033*t%dR" /* Set raster graphics resolution */
1335 "\033*r1A" ; /* Start raster graphics, rel. adressing */
1338 "\033*rB" /* end raster graphics */
1339 "\014" /* form feed */
1340 "\033E" ; /* Printer reset. */
1342 void pclwrite ( OFILE *f, unsigned char *buf, int n )
1344 while ( n > 0 && buf [ n-1 ] == 0 ) n-- ;
1345 fprintf( f->f, "\033*b%dW", n ) ;
1346 fwrite ( buf, n, 1, f->f ) ;
1350 /* Write a bit map as (raw) Portable Gray Map (PGM) format after
1351 decimating by a factor of 4. Sums bits in each 4x4-pel square
1352 to compute sample value. This function reduces each dimension
1353 of a bit map by 4 (it writes n*8/4 pixels per scan line and
1354 one scan line for every 4 in). The 17 possible sample values
1355 are spread linearly over the range 0-255. */
1357 void pgmwrite ( OFILE *f, uchar *buf, int n )
1359 static uchar gval [ MAXBITS * 8 / 4 ] ;
1360 static int init=0, lines=0 ;
1361 static uchar hbits [ 256 ], lbits [ 256 ] ;
1362 static int nybblecnt [ 16 ] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 } ;
1363 static uchar corr [ 17 ] = { 255, 239, 223, 207, 191, 175, 159, 143, 127,
1364 111, 95, 79, 63, 47, 31, 15, 0 } ;
1368 if ( ! init ) { /* build table of bit counts in each nybble */
1370 for ( i=0 ; i<256 ; i++ ) {
1371 hbits [ i ] = nybblecnt [ i >> 4 & 0x0f ] ;
1372 lbits [ i ] = nybblecnt [ i & 0x0f ] ;
1377 for ( m=n, p=gval, q=buf ; m-- > 0 ; q++ ) {
1378 *p++ += hbits [ *q ] ;
1379 *p++ += lbits [ *q ] ;
1382 if ( ( lines++ & 0x03 ) == 0x03 ) {
1383 for ( p=gval, m=2*n ; m-- > 0 ; p++ ) *p = corr [ *p ] ;
1384 fwrite ( gval, 1, 2*n, f->f ) ;
1385 memset ( gval, 0, 2*n ) ;
1390 /* Postscript image data is differentially coded vertically and
1391 run-length coded horizontally. A leading byte (n) defines the type
1392 of coding for subsequent data:
1394 0 repeat previous line
1395 1-127 n data bytes follow
1396 128-254 copy n-127 bytes from previous line
1397 255 n repeat the next character 'n' times
1399 The overhead for coding a copy is 2 bytes (copy count, data count),
1400 so copies > 2 bytes should be so coded. The overhead for coding a
1401 run is 4 bytes (255, count, byte, data count), so runs > 4 bytes
1402 should be so coded. Copies decode/execute faster and code more
1403 compactly so are preferred over runs.
1407 const char PSBEGIN [] = /* start of file */
1408 "%%!PS-Adobe-2.0 EPSF-2.0 \n"
1409 "%%%%Creator: efax (Copyright 1995 Ed Casas) \n"
1410 "%%%%Title: efix output\n"
1411 "%%%%Pages: (atend) \n"
1412 "%%%%BoundingBox: 0 0 %d %d \n"
1413 "%%%%BeginComments \n"
1414 "%%%%EndComments \n"
1415 "/val 1 string def \n"
1416 "/buf %d string def \n"
1418 " currentfile val readhexstring pop 0 get \n"
1423 " dup buf length ge { exit } if \n"
1424 " getval %% => index run_length \n"
1427 " pop buf length \n"
1429 " currentfile buf 3 index 3 index getinterval readhexstring pop pop\n"
1433 " pop getval getval %% => index run_length value \n"
1434 " 2 index 1 3 index 2 index add 1 sub %% => ... start 1 end \n"
1435 " { buf exch 2 index put } for \n"
1441 " add %% => index \n"
1446 "%%%%EndProlog \n" ;
1448 const char PSPAGE [] = /* start of page */
1449 "%%%%Page: %d %d \n"
1451 "%f %f translate \n"
1453 "%d %d %d [ %d %d %d %d %d %d ] { readbuf } image \n" ;
1455 const char PSPAGEEND [] = /* end of page */
1460 const char PSEND [] = /* end of file */
1462 "%%%%Pages: %d \n" ;
1465 void psinit ( OFILE *f, int newfile, int page, int w, int h, int n )
1470 msg ( "E2 can't happen (psinit)" ) ;
1474 ptw = w/f->xres * 72.0 ; /* convert to points */
1475 pth = h/f->yres * 72.0 ;
1478 fprintf ( f->f, PSBEGIN,
1479 (int) ptw, (int) pth, /* Bounding Box */
1480 n ) ; /* buffer string length */
1482 fprintf ( f->f, PSPAGE,
1483 page, page, /* page number */
1484 0.0, 0.0, /* shift */
1485 ptw, pth, /* scaling */
1486 w, h, 1, /* image size */
1487 w, 0, 0, -h, 0, h ) ; /* CTM */
1489 f->lastpageno = page ;
1493 char nhexout = 0, hexchars [ 16 ] = "0123456789abcdef" ;
1495 #define hexputc( f, c ) ( \
1496 putc ( hexchars [ (c) >> 4 ], f ), \
1497 putc ( hexchars [ (c) & 0x0f ], f ), \
1498 ( ( ( nhexout++ & 31 ) == 31 ) ? putc ( '\n', f ) : 0 ) )
1500 void hexputs ( FILE *f, uchar *p, int n )
1505 while ( n-- ) { c = *p++ ^ 0xff ; hexputc ( f, c ) ; }
1509 /* Encode into postscript. If not a repeated line, test (using
1510 index j) from current position (i) for possible encodings as:
1511 copy of > 2 bytes, runs of > 4 or data >=127. Otherwise the
1512 byte is skipped. Uncoded bytes are output from the last
1513 uncoded byte (l) before output of runs/copies. */
1515 void pswrite ( OFILE *f, unsigned char *buf, int n )
1518 static unsigned char last [ MAXBITS ] ;
1522 if ( ! f || ! buf || n<0 ) {
1523 msg ( "E2 can't happen (pswrite)" ) ;
1527 for ( j=0 ; j<n && buf[j]==last[j] && f->pslines ; j++ ) ;
1528 if ( j == n ) { /* repeat line */
1529 hexputc ( f->f, 0 ) ;
1535 for ( j=i ; j<n && buf[j]==last[j] && j-i<127 && f->pslines ; j++ ) ;
1536 if ( j-i > 2 ) { /* skip */
1537 hexputs ( f->f, buf+l, i-l ) ;
1538 hexputc ( f->f, j-i + 127 ) ;
1541 for ( j=i ; j<n && buf[j]==buf[i] && j-i<255 ; j++ ) ;
1542 if ( j-i > 4 ) { /* run */
1543 hexputs ( f->f, buf+l, i-l ) ;
1544 hexputc ( f->f, 255 ) ;
1545 hexputc ( f->f, j-i ) ;
1546 hexputc ( f->f, buf[i] ^ 0xff ) ;
1549 if ( i-l >= 127 ) { /* maximum data length */
1550 hexputs ( f->f, buf+l, i-l ) ;
1559 hexputs ( f->f, buf+l, i-l ) ;
1562 memcpy ( last, buf, n ) ;
1568 /* Write 2- and 4-byte integers to an image output file. Return
1571 int fwrite2 ( short s, OFILE *f )
1573 uchar *p = (void*) &s ;
1574 return fwrite ( bigendian ? p + sizeof(short) - 2 : p, 2, 1, f->f ) ;
1577 int fwrite4 ( long l, OFILE *f )
1579 uchar *p = (void*) &l ;
1580 return fwrite ( bigendian ? p + sizeof(long ) - 4 : p, 4, 1, f->f ) ;
1584 /* Write a TIFF directory tag. Returns 0 if OK, 1 on errors. */
1586 int wtag ( OFILE *f, int lng, short tag, short type, long count, long offset )
1590 err = err || ! fwrite2 ( tag, f ) ;
1591 err = err || ! fwrite2 ( type, f ) ;
1592 err = err || ! fwrite4 ( count, f ) ;
1594 err = err || ! fwrite4 ( offset, f ) ;
1596 err = err || ! fwrite2 ( offset, f ) ;
1597 err = err || ! fwrite2 ( 0, f ) ;
1600 if ( err ) msg ( "ES2 can't write TIFF tag" ) ;
1605 /* Write TIFF header and directory. File format based on Sam
1606 Leffler's tiff.h. Can only be used for single-image TIFFs
1607 because always seeks to start of file to re-write the
1610 #define NTAGS 17 /* number of tags in directory */
1611 #define NRATIO 2 /* number of floats (as ratios) */
1613 int tiffinit ( OFILE *f )
1615 int err=0, compr=1 ;
1618 fseek ( f->f, 0, SEEK_SET ) ;
1620 /* 0 ==> (start of TIFF file) */
1622 /* write magic, TIFF version and offset to directory */
1624 fwrite2 ( bigendian ? 0x4d4d : 0x4949, f ) ;
1628 /* 8 ==> directory */
1630 fwrite2 ( NTAGS, f ) ;
1632 /* figure out offsets within file and compression code */
1634 tdoff = 8 + 2 + NTAGS*12 + 4 ; /* offset to directory data */
1635 doff = tdoff + NRATIO*8 ; /* offset to image data */
1637 switch ( f->format ) {
1638 case O_TIFF_RAW: compr = 1 ; break ;
1639 case O_TIFF_FAX: compr = 3 ; break ;
1640 default: err = msg ( "E2can't happen(tiffinit)" ) ; break ;
1643 /* write directory tags, 12 bytes each */
1645 wtag( f, 1, 256, 4, 1, f->w ) ; /* width long */
1646 wtag( f, 1, 257, 4, 1, f->h ) ; /* length long */
1647 wtag( f, 0, 258, 3, 1, 1 ) ; /* bits/sample short */
1649 wtag( f, 0, 259, 3, 1, compr ) ; /* compresssion(g3=3) short */
1650 wtag( f, 0, 262, 3, 1, 0 ) ; /* photometric(0-min=white) short */
1651 wtag( f, 0, 266, 3, 1, 1 ) ; /* fill order(msb2lsb=1) short */
1652 wtag( f, 1, 273, 4, 1, doff ) ; /* strip offsets long */
1654 wtag( f, 0, 274, 3, 1, 1 ) ; /* orientation(1=normal) short */
1655 wtag( f, 0, 277, 3, 1, 1 ) ; /* samples/pixel short */
1656 wtag( f, 1, 278, 4, 1, f->h ) ; /* rows/strip long */
1657 wtag( f, 1, 279, 4, 1, f->bytes ) ; /* strip byte counts long */
1659 wtag( f, 1, 282, 5, 1, tdoff+0 ) ; /* xresolution ratio */
1660 wtag( f, 1, 283, 5, 1, tdoff+8 ) ; /* yresolution ratio */
1661 wtag( f, 0, 284, 3, 1, 1 ) ; /* storage(1=single plane) short */
1662 wtag( f, 1, 292, 4, 1, 0 ) ; /* g3options long */
1664 wtag( f, 0, 296, 3, 1, 2 ) ; /* resolution units(2=in,3=cm) short */
1665 wtag( f, 0, 327, 3, 1, 0 ) ; /* clean fax(0=clean) short */
1667 fwrite4 ( 0, f ) ; /* offset to next dir (no more) */
1669 /* ==> tdoff (tag data offset), write ratios for floats here */
1671 fwrite4 ( f->xres+0.5, f ) ;
1673 fwrite4 ( f->yres+0.5, f ) ;
1676 /* ==> doff (strip data offset), image data goes here */
1682 /* Convert array 'runs' of 'nr' run lengths into a bit map 'buf'. Returns
1683 the number of bytes filled. */
1685 int runtobit ( short *runs, int nr, uchar *buf )
1687 static uchar zerofill [ 9 ] = {
1688 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 } ;
1689 static uchar onefill [ 9 ] = {
1690 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff } ;
1692 uchar col=0, *buf0 = buf ;
1693 register short len, b=8, bytes ;
1695 while ( nr-- > 0 ) {
1697 if ( col ) *buf |= onefill [ b ] ; /* right bits of cur. byte */
1698 else *buf &= zerofill [ b ] ;
1699 if ( b > len ) { /* done fill */
1701 } else { /* continue to next byte */
1705 if ( ( bytes = len>>3 ) > 0 ) { /* fill >1 byte */
1706 memset ( buf, col, bytes ) ;
1710 *buf = col ; /* flood the rest */
1716 return buf - buf0 + ( b < 8 ) ;
1720 /* Write a PCX file header. */
1722 int fputi ( int i, OFILE *f )
1724 putc ( i & 0xff, f->f ) ;
1725 putc ( ( i >> 8 ) & 0xff, f->f ) ;
1729 void pcxinit ( OFILE *f )
1731 uchar buf [ 60 ] = { 0x0a, 3, 1, 1 } ; /* magic, version, compr, BPP */
1733 fwrite ( buf, 1, 4, f->f ) ; /* 4 */
1734 fputi ( 0, f ) ; /* 8 xmin, ymin, xmax, ymax */
1736 fputi ( f->w-1, f ) ;
1737 fputi ( f->h-1, f ) ;
1738 fputi ( f->xres, f ) ; /* 4 x and y dpi */
1739 fputi ( f->yres, f ) ;
1740 memset ( buf, 0, 48 ) ; /* 48 palette */
1741 fwrite ( buf, 1, 48, f->f ) ;
1742 putc ( 0, f->f ) ; /* 1 reserved */
1743 putc ( 1, f->f ) ; /* 1 planes per pixel */
1744 fputi ( (f->w+15)/16*2, f ) ; /* 2 bytes per line */
1745 memset ( buf, 0, 60 ) ; /* 60 zero */
1746 fwrite ( buf, 1, 60, f->f ) ;
1749 /* Write a PCX-compressed scan line. */
1751 void pcxwrite ( OFILE *of, uchar *p, int nb )
1759 for ( nb-- ; nb > 0 ; nb-- ) {
1761 if ( c == runc && n < 63 ) { /* continue run */
1763 } else { /* terminate run */
1764 if ( n > 1 || ( ( runc & 0xc0 ) == 0xc0 ) ) /* output as run */
1765 putc ( n | 0xc0, f ) ;
1767 runc = c ; /* start new run */
1774 if ( n > 1 || ( ( runc & 0xc0 ) == 0xc0 ) ) /* output as run */
1775 putc ( n | 0xc0, f ) ;
1781 /* Begin/end output pages. If not starting first page (0), terminate
1782 previous page. If output filename pattern is defined, [re-]opens that
1783 file. If not terminating last page (page==EOF), writes file header.
1784 Returns 0 or 2 on errors. */
1786 int nextopage ( OFILE *f, int page )
1790 uchar *p, codes [ ( RTCEOL * EOLBITS ) / 8 + 3 ] ;
1792 if ( f->f ) { /* terminate previous page */
1794 switch ( f->format ) {
1801 for ( p = codes, i=0 ; i<RTCEOL ; i++ )
1802 p = putcode ( &f->e, EOLCODE, EOLBITS, p ) ;
1803 nb = putcode ( &f->e, 0, 0, p ) - codes ;
1804 fwrite ( codes, 1, nb, f->f ) ;
1806 if ( f->format == O_TIFF_FAX ) tiffinit ( f ) ;
1809 tiffinit(f) ; /* rewind & update TIFF header */
1812 fprintf ( f->f, PCLEND ) ;
1815 fprintf ( f->f, PSPAGEEND ) ;
1816 if ( f->fname || page<0 ) fprintf ( f->f, PSEND, f->lastpageno ) ;
1820 fseek ( f->f, 0, SEEK_SET ) ;
1825 if ( ferror ( f->f ) ) {
1826 err = msg ("ES2output error:" ) ;
1828 msg ( "F+ wrote %s as %dx%d pixel %.fx%.f dpi %s page",
1829 f->cfname, f->w, f->h, f->xres, f->yres,
1830 oformatname [f->format] ) ;
1832 switch ( f->format ) {
1834 msg ( "F (%d lines)", f->pslines ) ;
1838 msg ( "F (%d bytes)", f->bytes ) ;
1849 if ( ! err && page >= 0 ) { /* open new file */
1851 sprintf ( f->cfname, f->fname, page+1, page+1, page+1 ) ;
1854 f->f = fopen ( f->cfname, ( f->format == O_PS ) ? "w" : "wb+" ) ;
1856 f->f = freopen ( f->cfname, ( f->format == O_PS ) ? "w" : "wb+", f->f ) ;
1859 err = msg ("ES2can't open output file %s:", f->cfname ) ;
1863 strcpy ( f->cfname, "standard output" ) ;
1867 /* start new page */
1869 if ( ! err && page >= 0 ) {
1870 switch ( f->format ) {
1872 fprintf ( f->f, "P4 %d %d\n", f->w, f->h ) ;
1875 fprintf ( f->f, "P5 %d %d %d\n", f->w/4, f->h/4, 255 ) ;
1879 if ( f->format == O_TIFF_FAX ) tiffinit ( f ) ;
1880 p = putcode ( &f->e, EOLCODE, EOLBITS, codes ) ;
1882 fwrite ( codes, 1, nb, f->f ) ;
1888 fprintf ( f->f, PCLBEGIN, (int) f->xres ) ;
1891 psinit ( f, ( f->fname || page==0 ), page+1, f->w, f->h, f->w/8 ) ;
1895 fseek ( f->f, 0, SEEK_SET ) ;
1900 if ( ferror ( f->f ) ) err = msg ("ES2output error:" ) ;
1903 /* only count lines/bytes for those formats that don't have
1904 headers or where we will update the headers on closing */
1906 switch ( f->format ) {
1920 /* Output scan line of nr runs no times to output file f. */
1922 void writeline ( OFILE *f, short *runs, int nr, int no )
1925 uchar *p, buf [ MAXCODES ] ;
1927 /* if line to be output, convert to right format */
1930 switch ( f->format ) {
1938 nb = runtobit ( runs, nr, buf ) ;
1945 /* output `no' times. */
1947 while ( no-- > 0 ) {
1948 switch ( f->format ) {
1952 fwrite ( buf, 1, nb, f->f ) ;
1955 pgmwrite ( f, buf, nb ) ;
1959 p = runtocode ( &f->e, runs, nr, buf ) ;
1960 p = putcode ( &f->e, EOLCODE, EOLBITS, p ) ;
1962 fwrite ( buf, 1, nb, f->f ) ;
1965 pclwrite ( f, buf, nb ) ;
1968 pswrite ( f, buf, nb ) ;
1971 pcxwrite ( f, buf, nb ) ;
1975 /* only count lines/bytes for those formats that don't have
1976 headers or where we will update the headers on closing */
1978 switch ( f->format ) {
1993 /* Initialize new output file. If fname is NULL, stdout will be used for
1996 void newOFILE ( OFILE *f, int format, char *fname,
1997 float xres, float yres, int w, int h )
2000 f->format = format ;
2007 newENCODER ( &f->e ) ;
2010 /* Read a bitmap to use as a font and fill in the font data. If
2011 the file name is null, empty, or there are errors, the font is
2012 initialized to the built-in font. Returns 0 if OK, 2 on
2015 int readfont ( char *fname, faxfont *font )
2017 int err=0, i, j, n=0, nr, nb, fontok=0, pels ;
2018 char *fnames [2] = { 0, 0 } ;
2019 short runs [ MAXRUNS ] ;
2022 if ( fname && *fname ) {
2026 newIFILE ( &f, fnames ) ;
2028 if ( nextipage ( &f, 0 ) ) {
2029 err = msg ( "E2 can't open font file %s", fnames[0] ) ;
2033 while ( ! err && ( nr = readline ( &f, runs, &pels ) ) >= 0 ) {
2034 if ( nb+pels/8 < MAXFONTBUF ) {
2035 nb += runtobit ( runs, nr, font->buf+nb ) ;
2037 err = msg ("E2font file %s too large (max %d bytes)",
2038 fnames[0], MAXFONTBUF ) ;
2042 if ( ! err && nb != f.page->w * f.page->h / 8 )
2043 err = msg ( "E2 read %d bytes of font data for %dx%d bitmap",
2044 nb, f.page->w, f.page->h ) ;
2046 if ( ! err && ( f.page->w / 256 > MAXFONTW || f.page->h > MAXFONTH ) ) {
2047 err = msg ( "E2font size (%dx%d) too large", f.page->w, f.page->h ) ;
2051 font->w = font->h = 0 ;
2053 font->w = f.page->w / 256 ;
2054 font->h = f.page->h ;
2055 for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;
2056 msg ("Iread %dx%d font %s (%d bytes)", font->w, font->h, fname, nb ) ;
2066 if ( ! fontok ) { /* use built-in font */
2068 font->w = STDFONTW ;
2069 font->h = STDFONTH ;
2071 for ( i=j=0 ; j<STDFONTBUF ; i++ ) /* expand bit map */
2072 if ( stdfont [ i ] == 0 )
2073 for ( n = stdfont [ ++i ] ; n > 0 ; n-- )
2074 font->buf [ j++ ] = 0 ;
2076 font->buf [ j++ ] = stdfont [ i ] ;
2078 if ( i != 1980 ) err = msg ( "E2can't happen(readfont)" ) ;
2080 for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;
2085 #endif /* UCLINUX */
2088 /* Initialize bit reversal lookup tables (note that the
2089 `normalbits' array is the one actually used for the bit
2092 void initbittab ( void )
2095 for ( i=0 ; i<256 ; i++ )
2096 normalbits [ reversebits [ i ] = i ] =
2097 ( i& 1 ? 128:0 ) | ( i& 2 ? 64:0 ) | ( i& 4 ? 32:0 ) | ( i& 8 ? 16:0 ) |
2098 ( i&16 ? 8:0 ) | ( i&32 ? 4:0 ) | ( i&64 ? 2:0 ) | ( i&128 ? 1:0 ) ;
2102 /* T.4 Encoding/Decoding */
2104 /* Table-lookup decoder for variable-bit-length codewords. The table index
2105 is the N most recently undecoded bits with the first (oldest) undecoded
2106 bit as the MS bit. If the N bits uniquely identify a codeword then the
2107 indexed 'code' member identifies the code, otherwise it is zero. The
2108 'bits' member gives the number of bits to be considered decoded (to be
2109 removed from the bit stream) and the 'next' element is a pointer to the
2110 table to use for decoding the next part of the bit sequence.
2112 For T.4 decoding the longest T.4 codeword is 13 bits. The implementation
2113 below uses two tables of 512 elements (N=9 bits) for each colour.
2114 Codewords longer than 9 bits require a second lookup. Since all
2115 codewords longer than than 9 bits have a 4-bit zero prefix it is
2116 possible to use only one secondary 9-bit lookup table by dropping only
2117 the first 4 bits after the first lookup. The code indentifier is the run
2118 length + 1. A separate table is used for decoding the variable-length
2121 For undefined codewords, one bit is skipped and decoding continues at
2122 the white code table. */
2124 /* the lookup tables for each colour and the fill lookup table */
2127 dtab tw1 [ 512 ], tw2 [ 512 ], tb1 [ 512 ], tb2 [ 512 ], fill [ 512 ] ;
2128 static char tabinit=0 ;
2130 /* Add code cword shifted left by shift to decoding table tab. */
2132 void addcode ( dtab *tab, int cword, int shift,
2133 short code, short bits, dtab *next )
2135 int i, n = 1 << shift ;
2137 for ( i = cword << shift ; n-- > 0 ; i++ ) {
2138 tab[i].code = code ;
2139 tab[i].bits = bits ;
2140 tab[i].next = next ;
2144 /* Initialize the decoding table for one colour using the codes in the T.4
2145 table p0. t1 and t2 are the two decoding tables and ot is the first
2146 table of the other colour. */
2148 void init1dtab ( t4tab *p0, dtab *t1, dtab *t2, dtab *ot )
2151 for ( p = p0 ; p->code ; p++ )
2152 if ( p->bits <= 9 ) {
2153 addcode ( t1, p->code, 9 - p->bits, p->rlen + 1, p->bits,
2154 ( p - p0 ) > 63 ? t1 : ot ) ;
2156 addcode ( t1, p->code >> ( p->bits - 9 ), 0, 0, 4, t2 ) ;
2157 addcode ( t2, p->code, 13 - p->bits, p->rlen + 1, p->bits - 4,
2158 ( p - p0 ) > 63 ? t1 : ot ) ;
2161 #endif /* UCLINUX */
2164 /* Initialize a T.4 decoder. */
2167 void newDECODER ( DECODER *d )
2173 /* undefined codes */
2175 addcode ( tw1, 0, 9, 0, 1, tw1 ) ;
2176 addcode ( tw2, 0, 9, 0, 1, tw1 ) ;
2177 addcode ( tb1, 0, 9, 0, 1, tw1 ) ;
2178 addcode ( tb2, 0, 9, 0, 1, tw1 ) ;
2179 addcode ( fill, 0, 9, 0, 1, tw1 ) ;
2183 addcode ( tw1, 0, 0, 0, 4, tw2 ) ;
2184 addcode ( tw2, 0, 2, 0, 7, fill ) ;
2185 addcode ( tb1, 0, 0, 0, 4, tb2 ) ;
2186 addcode ( tb2, 0, 2, 0, 7, fill ) ;
2188 addcode ( fill, 0, 0, 0, 9, fill ) ;
2189 for ( i=0 ; i<=8 ; i++ )
2190 addcode ( fill, 1, i, -1, 9-i, tw1 ) ;
2192 /* white and black runs */
2194 init1dtab ( wtab, tw1, tw2, tb1 ) ;
2195 init1dtab ( btab, tb1, tb2, tw1 ) ;
2200 /* initialize decoder to starting state */
2207 #endif /* UCLINUX */
2209 /* T.4 coding table and default font for efax/efix */
2211 /* T.4 1-D run-length coding tables. codes must be in run length
2212 order for runtocode(). */
2214 static t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] = { /* runs of white */
2216 /* Terminating White Codes */
2218 {53,8,0}, {7,6,1}, {7,4,2}, {8,4,3}, {11,4,4}, {12,4,5},
2219 {14,4,6}, {15,4,7}, {19,5,8}, {20,5,9}, {7,5,10}, {8,5,11},
2220 {8,6,12}, {3,6,13}, {52,6,14}, {53,6,15}, {42,6,16}, {43,6,17},
2221 {39,7,18}, {12,7,19}, {8,7,20}, {23,7,21}, {3,7,22}, {4,7,23},
2222 {40,7,24}, {43,7,25}, {19,7,26}, {36,7,27}, {24,7,28}, {2,8,29},
2223 {3,8,30}, {26,8,31}, {27,8,32}, {18,8,33}, {19,8,34}, {20,8,35},
2224 {21,8,36}, {22,8,37}, {23,8,38}, {40,8,39}, {41,8,40}, {42,8,41},
2225 {43,8,42}, {44,8,43}, {45,8,44}, {4,8,45}, {5,8,46}, {10,8,47},
2226 {11,8,48}, {82,8,49}, {83,8,50}, {84,8,51}, {85,8,52}, {36,8,53},
2227 {37,8,54}, {88,8,55}, {89,8,56}, {90,8,57}, {91,8,58}, {74,8,59},
2228 {75,8,60}, {50,8,61}, {51,8,62}, {52,8,63},
2230 /* Make Up White Codes */
2232 {27,5,64}, {18,5,128}, {23,6,192}, {55,7,256}, {54,8,320}, {55,8,384},
2233 {100,8,448}, {101,8,512}, {104,8,576}, {103,8,640}, {204,9,704}, {205,9,768},
2234 {210,9,832}, {211,9,896}, {212,9,960}, {213,9,1024},{214,9,1088},{215,9,1152},
2235 {216,9,1216},{217,9,1280},{218,9,1344},{219,9,1408},{152,9,1472},{153,9,1536},
2236 {154,9,1600},{24,6,1664}, {155,9,1728},
2238 /* Extended Make Up Codes (Black and White) */
2240 {8,11,1792}, {12,11,1856},{13,11,1920},{18,12,1984},{19,12,2048},{20,12,2112},
2241 {21,12,2176},{22,12,2240},{23,12,2304},{28,12,2368},{29,12,2432},{30,12,2496},
2246 static t4tab btab [ ( 64 + 27 + 13 ) + 1 ] = { /* runs of black */
2248 /* Terminating Black Codes */
2250 {55,10,0}, {2,3,1}, {3,2,2}, {2,2,3}, {3,3,4}, {3,4,5},
2251 {2,4,6}, {3,5,7}, {5,6,8}, {4,6,9}, {4,7,10}, {5,7,11},
2252 {7,7,12}, {4,8,13}, {7,8,14}, {24,9,15}, {23,10,16}, {24,10,17},
2253 {8,10,18}, {103,11,19}, {104,11,20}, {108,11,21}, {55,11,22}, {40,11,23},
2254 {23,11,24}, {24,11,25}, {202,12,26}, {203,12,27}, {204,12,28}, {205,12,29},
2255 {104,12,30}, {105,12,31}, {106,12,32}, {107,12,33}, {210,12,34}, {211,12,35},
2256 {212,12,36}, {213,12,37}, {214,12,38}, {215,12,39}, {108,12,40}, {109,12,41},
2257 {218,12,42}, {219,12,43}, {84,12,44}, {85,12,45}, {86,12,46}, {87,12,47},
2258 {100,12,48}, {101,12,49}, {82,12,50}, {83,12,51}, {36,12,52}, {55,12,53},
2259 {56,12,54}, {39,12,55}, {40,12,56}, {88,12,57}, {89,12,58}, {43,12,59},
2260 {44,12,60}, {90,12,61}, {102,12,62}, {103,12,63},
2262 /* Make Up Black Codes */
2264 {15,10,64}, {200,12,128},{201,12,192},{91,12,256}, {51,12,320}, {52,12,384},
2265 {53,12,448}, {108,13,512},{109,13,576},{74,13,640}, {75,13,704}, {76,13,768},
2266 {77,13,832}, {114,13,896},{115,13,960},{116,13,1024},{117,13,1088},
2268 {119,13,1216},{82,13,1280},{83,13,1344},{84,13,1408},{85,13,1472},{90,13,1536},
2269 {91,13,1600},{100,13,1664},{101,13,1728},
2271 /* Extended Make Up Codes (Black and White) */
2273 {8,11,1792}, {12,11,1856},{13,11,1920},{18,12,1984},{19,12,2048},{20,12,2112},
2274 {21,12,2176},{22,12,2240},{23,12,2304},{28,12,2368},{29,12,2432},{30,12,2496},
2280 /* The built-in 8x16 font. Runs of zeroes are coded as 0
2281 followed by the repetition count. */
2284 uchar stdfont [ 1980 ] = {
2285 0,255,0,255,0,194,8,4,12,10,18,0,3,16,4,8,20,8,4,8,20,0,1,10,8,4,
2286 4,10,18,0,2,16,4,8,20,4,0,68,20,0,1,8,0,2,12,6,48,0,5,2,0,43,14,32,
2287 56,0,2,12,0,1,32,0,1,2,0,1,14,0,1,32,8,4,32,56,0,14,6,8,48,0,40,8,
2288 0,1,18,0,6,30,0,4,4,0,11,4,8,18,20,18,12,0,2,8,8,20,20,4,8,20,20,
2289 0,1,20,4,8,10,20,18,0,2,8,8,20,20,8,0,1,24,8,4,8,10,20,12,0,2,8,4,
2290 8,20,16,8,8,20,54,10,8,4,8,10,20,0,2,16,4,8,20,4,0,1,20,0,33,12,20,
2291 18,28,48,12,12,8,8,8,0,4,2,28,8,28,28,4,62,28,62,28,28,0,5,60,28,
2292 12,60,14,56,62,30,14,34,62,62,33,16,33,34,12,60,12,60,30,127,34,33,
2293 65,34,34,62,8,32,8,8,0,1,24,0,1,32,0,1,2,0,1,16,0,1,32,8,4,32,8,0,
2294 7,16,0,6,8,8,8,0,36,4,14,0,1,34,8,12,18,28,24,0,3,28,0,1,24,0,1,28,
2295 28,8,0,1,30,0,2,8,28,0,1,100,100,98,0,6,18,31,14,0,8,56,0,7,13,0,
2296 5,32,36,4,8,20,20,20,18,0,2,4,8,20,20,8,16,20,20,8,20,4,8,20,20,20,
2297 0,2,8,8,20,20,8,32,20,0,33,12,20,18,42,73,18,24,8,8,42,8,0,3,4,34,
2298 24,34,34,12,32,34,2,34,34,0,2,2,0,1,16,2,34,12,34,18,36,32,16,18,
2299 34,8,8,34,16,51,50,18,34,18,34,32,8,34,33,73,34,34,2,8,16,8,8,0,1,
2300 24,0,1,32,0,1,2,0,1,16,0,1,32,0,2,32,8,0,7,16,0,6,8,8,8,0,36,15,16,
2301 65,34,8,18,0,1,34,4,0,3,34,0,1,36,8,2,2,0,2,58,0,2,56,34,0,1,36,36,
2302 18,0,1,12,12,12,12,12,12,24,18,62,62,62,62,62,62,62,62,36,34,12,12,
2303 12,12,12,0,1,18,34,34,34,34,34,32,36,0,5,12,0,10,52,0,6,8,0,6,32,
2304 0,34,12,0,1,63,40,74,18,0,1,16,4,20,8,0,3,4,34,40,2,2,20,32,32,2,
2305 34,34,24,24,4,0,1,8,2,78,18,34,32,34,32,16,32,34,8,8,36,16,51,50,
2306 33,34,33,34,32,8,34,33,73,20,34,4,8,16,8,20,0,2,28,44,14,30,28,62,
2307 30,44,56,60,34,8,82,44,28,44,30,22,30,62,34,34,65,34,34,62,8,8,8,
2308 0,35,12,20,16,62,34,8,16,0,1,77,4,0,3,93,0,1,24,8,2,12,0,1,34,58,
2309 0,2,8,34,0,1,40,40,100,4,12,12,12,12,12,12,40,32,32,32,32,32,8,8,
2310 8,8,34,50,18,18,18,18,18,34,35,34,34,34,34,34,60,40,28,28,28,28,28,
2311 28,54,14,28,28,28,28,56,56,56,56,2,44,28,28,28,28,28,8,29,34,34,34,
2312 34,34,44,34,0,33,12,0,1,18,24,52,12,0,1,16,4,42,8,0,3,8,34,8,2,2,
2313 36,60,32,4,34,34,24,24,8,127,4,2,82,18,34,32,34,32,16,32,34,8,8,40,
2314 16,45,42,33,34,33,34,48,8,34,33,73,20,20,4,8,8,8,20,0,2,34,50,16,
2315 34,34,16,34,50,8,4,36,8,109,50,34,50,34,24,32,16,34,34,73,34,34,2,
2316 4,8,16,57,0,34,12,36,16,34,20,0,1,40,0,1,81,28,18,127,0,1,89,0,2,
2317 127,12,2,0,1,34,58,28,0,1,8,34,36,40,40,24,4,18,18,18,18,18,18,40,
2318 32,32,32,32,32,8,8,8,8,34,50,33,33,33,33,33,20,37,34,34,34,34,20,
2319 34,40,34,34,34,34,34,34,9,16,34,34,34,34,8,8,8,8,30,50,34,34,34,34,
2320 34,0,1,34,34,34,34,34,34,50,34,0,33,12,0,1,18,12,8,25,0,1,16,4,8,
2321 127,0,1,127,0,1,8,34,8,4,12,68,2,60,8,28,30,0,2,16,0,1,2,28,82,18,
2322 60,32,34,60,30,32,62,8,8,56,16,45,42,33,34,33,60,28,8,34,18,85,8,
2323 20,8,8,8,8,34,0,2,2,34,32,34,34,16,34,34,8,4,40,8,73,34,34,34,34,
2324 16,32,16,34,34,73,20,34,4,24,8,12,78,0,35,36,60,34,62,0,1,36,0,1,
2325 81,36,36,1,28,85,0,2,8,16,2,0,1,34,26,28,0,1,8,34,18,18,22,106,0,
2326 1,18,18,18,18,18,18,47,32,60,60,60,60,8,8,8,8,122,42,33,33,33,33,
2327 33,8,45,34,34,34,34,20,34,36,2,2,2,2,2,2,9,32,34,34,34,34,8,8,8,8,
2328 34,34,34,34,34,34,34,127,38,34,34,34,34,34,34,34,0,33,8,0,1,63,10,
2329 22,37,0,1,16,4,0,1,8,0,3,8,34,8,8,2,126,2,34,8,34,2,0,2,8,127,4,16,
2330 86,63,34,32,34,32,16,34,34,8,8,36,16,45,38,33,60,33,36,6,8,34,18,
2331 54,20,8,16,8,8,8,34,0,2,30,34,32,34,62,16,34,34,8,4,56,8,73,34,34,
2332 34,34,16,28,16,34,20,85,8,20,8,4,8,16,0,35,8,36,16,34,8,8,18,0,1,
2333 81,26,72,1,0,1,34,0,2,8,30,28,0,1,34,10,28,0,1,8,28,9,22,17,22,4,
2334 63,63,63,63,63,63,120,32,32,32,32,32,8,8,8,8,34,42,33,33,33,33,33,
2335 20,41,34,34,34,34,8,34,34,30,30,30,30,30,30,63,32,62,62,62,62,8,8,
2336 8,8,34,34,34,34,34,34,34,0,1,42,34,34,34,34,20,34,20,0,35,18,10,41,
2337 34,0,1,16,4,0,1,8,0,3,16,34,8,16,2,4,2,34,16,34,2,0,2,4,0,1,8,0,1,
2338 73,33,34,32,34,32,16,34,34,8,8,34,16,33,38,33,32,33,34,2,8,34,18,
2339 34,20,8,16,8,4,8,0,3,34,34,32,34,32,16,38,34,8,4,36,8,73,34,34,34,
2340 34,16,2,16,34,20,34,20,20,16,8,8,8,0,35,12,20,16,62,62,8,10,0,1,77,
2341 0,1,36,1,0,1,28,0,6,34,10,0,4,18,42,34,42,28,33,33,33,33,33,33,72,
2342 32,32,32,32,32,8,8,8,8,34,38,33,33,33,33,33,34,49,34,34,34,34,8,60,
2343 34,34,34,34,34,34,34,72,32,32,32,32,32,8,8,8,8,34,34,34,34,34,34,
2344 34,8,50,34,34,34,34,20,34,20,0,33,12,0,1,18,42,73,34,0,1,8,8,0,1,
2345 8,12,0,1,24,16,34,8,32,34,4,34,34,16,34,34,24,24,2,0,1,16,16,32,33,
2346 34,16,36,32,16,18,34,8,8,33,16,33,34,18,32,18,34,2,8,34,12,34,34,
2347 8,32,8,4,8,0,3,34,34,16,38,34,16,26,34,8,4,34,8,73,34,34,34,38,16,
2348 2,16,38,8,34,34,8,32,8,8,8,0,35,12,15,16,65,8,8,4,0,1,34,0,1,18,0,
2349 5,127,0,3,54,10,0,4,36,79,68,79,32,33,33,33,33,33,33,72,16,32,32,
2350 32,32,8,8,8,8,36,38,18,18,18,18,18,0,1,18,34,34,34,34,8,32,34,34,
2351 34,34,34,34,34,72,16,34,34,34,34,8,8,8,8,34,34,34,34,34,34,34,8,34,
2352 38,38,38,38,8,34,8,0,33,12,0,1,18,28,6,29,0,1,8,8,0,2,12,0,1,24,32,
2353 28,8,62,28,4,28,28,16,28,28,24,24,0,3,16,28,33,60,14,56,62,16,14,
2354 34,62,112,33,30,33,34,12,32,12,34,60,8,28,12,34,34,8,62,8,2,8,0,3,
2355 29,60,14,26,28,16,2,34,8,4,33,8,73,34,28,60,26,16,60,14,26,8,34,34,
2356 8,62,8,8,8,0,35,12,4,62,0,1,8,8,36,0,1,28,0,11,42,10,0,5,66,71,66,
2357 32,33,33,33,33,33,33,79,14,62,62,62,62,62,62,62,62,56,34,12,12,12,
2358 12,12,0,1,44,28,28,28,28,8,32,36,29,29,29,29,29,29,55,14,28,28,28,
2359 28,8,8,8,8,28,34,28,28,28,28,28,0,1,92,26,26,26,26,8,60,8,0,36,8,
2360 0,3,6,48,0,2,24,0,2,32,0,11,48,0,21,6,0,9,14,2,56,0,1,127,0,7,2,0,
2361 2,4,0,5,32,2,0,7,16,0,1,6,8,48,0,35,12,0,4,8,24,0,13,32,10,0,1,4,
2362 0,6,32,0,7,4,0,31,4,0,21,16,32,16,0,81,3,0,21,28,0,2,56,0,5,32,2,
2363 0,7,48,0,39,12,0,19,32,0,2,24,0,6,30,0,7,24,0,31,24,0,21,48,32,48,
2366 #endif /* UCLINUX */