📄 efaxlib.c
字号:
after each scan line by calling with nb=0 and in=NULL. */#define putbits( c , b ) { x = ( x << (b) ) | (c) ; shift += (b) ; \ if ( shift >= 0 ) { *out++ = x >> shift ; shift -= 8 ; } }void copybits ( u_char *in , int from , short nb ){ u_char *f ; short bits ; static u_char *out ; static short x, shift ; static unsigned char right [ 9 ] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff } ; if ( ! nb ) { /* reset for new scan line */ if ( in ) out = in ; else putbits ( 0, -shift ) ; /* or flush bit buffer */ x = 0 ; shift = -8 ; } else { f = in + ( from >> 3 ) ; bits = 8 - ( from & 7 ) ; if ( nb >= bits ) { putbits ( *f++ & right [ bits ] , bits ) ; nb -= bits ; } else { putbits ( ( *f >> ( bits - nb ) ) & right [ bits ] , nb ) ; nb = 0 ; } while ( nb >= 8 ) { putbits ( *f++ , 8 ) ; nb -= 8 ; } if ( nb > 0 ) putbits ( *f >> ( 8 - nb ) , nb ); }} /* Generate scan line 'line' of string 'txt' using font `font' and store the runs in 'runs'. Sets 'pels' to line width if not null. Returns number of runs coded. */int texttorun( u_char *txt, pbmfont *font, short line, short *runs, int *pels ){ u_char *in, out [ MAXLINELEN * MAXFONTW / 8 + 1 ] ; int i, nc = 0, cw, nr ; cw = font->w ; if ( line >= font->h ) line = font->h - 1 ; in = font->buf + 256/8 * cw * line ; copybits ( out, 0, 0 ) ; for ( i=0 ; txt[i] && i < MAXLINELEN ; i++ ) { copybits ( in, font->offset [ txt[i] ], cw ) ; nc++ ; while ( ( txt[i] == HT ) && ( nc & 7 ) ) { /* tab */ copybits ( in, font->offset [ ' ' ], cw ) ; nc++ ; } } copybits ( 0, 0, 0 ) ; if ( pels ) *pels = cw * nc ; nr = bittorun ( out, ( nc*cw + 7 )/8, runs ) ; return nr ;} /* Image File Input Functions *//* Read run lengths for one scan line from T.4-coded file f into buffer runs using decoder state d. If pointer pels is not null it is used to save pixel count. Returns number of runs stored, EOF on RTC, or -2 on EOF or other error. */int readruns ( DECODER *d, FILE *f, short *runs, int *pels ){ int err=0, c=EOF, n ; register int x ; dtab *tab, *t ; short shift ; short *p, *maxp, *q, len=0, npad=0 ; maxp = ( p = runs ) + MAXRUNS ; x = d->x ; shift = d->shift ; tab = d->tab ; /* restore decoder state */ do { do { while ( shift < 0 ) { if ( ( c = getc ( f ) ) == EOF ) { x = ( x << 15 ) | 1 ; shift += 15 ; /* EOL pad at EOF */ npad++ ; } else { x = ( x << 8 ) | c ; shift += 8 ; } } t = tab + ( ( x >> shift ) & 0x1ff ) ; tab = t->next ; shift -= t->bits ; } while ( ! t->code ) ; if ( p < maxp ) *p++ = t->code ; } while ( t->code != -1 ) ; d->x = x ; d->shift = shift ; d->tab = tab ; /* save state */ if ( npad > 1 ) msg ("W EOF before RTC" ) ; if ( p >= maxp ) msg ( "Wrun length buffer overflow" ) ; /* combine make-up and terminating codes and remove +1 offset in run lengths */ n = p - runs - 1 ; for ( p = q = runs ; n-- > 0 ; ) if ( *p > 64 && n-- > 0 ) { len += *q++ = p[0] + p[1] - 2 ; p+=2 ; } else { len += *q++ = *p++ - 1 ; } n = q - runs ; /* check for RTC and errors */ if ( len ) d->eolcnt = 0 ; else if ( ++(d->eolcnt) >= RTCEOL ) err = EOF ; if ( c == EOF ) if ( ferror ( f ) ) err = -msg ("ES2error reading fax file:") ; else err = -2 ; if ( pels ) *pels = len ; return err ? err : n ;}/* Read a scan line from the current page of IFILE f. Stores number of runs in runs and line width in pels if not null. Pages ends at EOF. Text pages also end if a complete text line would not fit or if formfeed is the first character of a line. PBM pages also end when all lines in the bitmap have been read. Fax pages also end at RTC. Returns number of runs stored or EOF at end of page. */int readline ( IFILE *f, short *runs, int *pels ){ int nr = 0 ; u_char bits [ MAXBITS ] ; if ( f->lines ) switch ( f->format ) { case TEXT : if ( f->txtlines <= 0 ) { /* need another text line */ if ( fgets ( f->text, MAXLINELEN, f->f ) ) { f->txtlines = f->font->h ; if ( strchr ( f->text, FF ) ) { f->lines = 0 ; /* no more lines in this page */ nr = EOF ; /* don't return any */ } } else { nr = EOF ; } } if ( nr != EOF ) { nr = texttorun( (u_char*) f->text, f->font, f->font->h - f->txtlines, runs, pels ) ; f->txtlines-- ; } break ; case PBM: if ( fread ( bits, 1, f->Bw, f->f ) != f->Bw ) { nr = EOF ; } else { nr = bittorun ( bits, f->Bw, runs ) ; if ( pels ) *pels = f->Bw * 8 ; } break ; case FAX: nr = readruns ( &(f->d), f->f, runs, pels ) ; break ; } else nr = EOF ; if ( nr >= 0 && f->lines > 0 ) f->lines-- ; return nr ;}/* Skip to start of next/same (if dp=0) page image, possibly within same file. For text files, continues reading from the current file unless at EOF. Other formats skip to next file in list of file names. Uses stdin if file name is '-'. Checks for correct file headers (if any) and initializes relevant parts of the IFILE. Returns f if OK, NULL on error. */IFILE *nextipage ( IFILE *f, int dp ){ int err = 0, newfile=1, stdinput=0 ; short runs [ MAXRUNS ] ; char *fn = "next page" ; static pbmfont defaultfont ; /* default font used for text files */ /* seek to start of next/same page within current file (if any) */ if ( f->f ) switch ( f->format ) { case TEXT: if ( dp ) while ( readline ( f, runs, 0 ) >= 0 ) ; else if ( fseek ( f->f, f->start, SEEK_SET ) ) err = msg ("ES2can't re-read page:" ) ; if ( ! feof ( f->f ) && ! ferror ( f->f ) ) newfile = 0 ; break ; case PBM: break ; case FAX: break ; } if ( newfile && ! err ) { /* open same/next file */ if ( dp && f->fname && *f->fname ) f->fname++ ; if ( ! f->fname || ! *f->fname ) err = 1 ; else { fn = *f->fname ; if ( ! strcmp ( fn, "-" ) ) { stdinput = 1 ; if ( f->f != stdin ) fclose ( f->f ) ; rewind ( f->f = stdin ) ; } else { if ( f->f ) fclose ( f->f ) ; f->f = fopen ( fn, ( f->format==TEXT ) ? "r" : "rb" ) ; } if ( ! f->f ) err = msg ( "ES2can't open %s:", fn ) ; } } /* read file/subfile header and set relevant IFILE struct variables */ if ( ! err ) { switch ( f->format ) { /* initialize f */ case TEXT: if ( ! f->font ) readfont ( 0, f->font = &defaultfont ) ; if ( ! f->pglines ) f->pglines = DEFPGLINES ; f->start = ftell ( f->f ) ; f->lines = ( ( f->pglines * f->font->h ) / f->font->h ) * f->font->h ; break ; case PBM: /* get width & height */ if ( openpbm ( f->f, &f->w, &f->h ) ) err = 2 ; else if ( f->w % 8 ) err = msg ( "E2 PBM width must be multiple of 8" ) ; else { f->Bw = f->w / 8 ; f->lines = f->h ; } break ; case FAX: newDECODER ( &f->d ) ; if ( readruns ( &f->d, f->f, runs, 0 ) < 0 ) /* skip first EOL */ msg ( "Wno EOL: probably not fax file" ) ; f->lines = -1 ; break ; } msg ("I+opened %s", stdinput ? "standard input" : fn ) ; switch ( f->format ) { case FAX: msg ( "I as fax file" ) ; break ; case PBM: msg ( "I as %dx%d PBM file", f->w, f->h ) ; break ; case TEXT: msg ( "I as %d-line/page text file with %dx%d font", f->pglines, f->font->w, f->font->h ) ; break ; } } if ( err ) f->lines = 0 ; return err ? 0 : f ;}/* Initialize an IFILE. */void newIFILE ( IFILE *f, int format, char **fname ){ f->f = 0 ; f->format = format ; f->fname = fname ; f->lines = 0 ; f->txtlines = 0 ; f->font = 0 ; f->pglines = 0 ;} /* Image File Output Functions *//* Strings and function to write a bit map in HP-PCL format. The only compression is removal of trailing zeroes. Margins and resolution are set before first write. */char *PCLBEGIN = "\033E" /* Printer reset. */ "\033&l0E" /* top margin = 0 */ "\033&a0L" /* left margin = 0 */ "\033*t%dR" /* Set raster graphics resolution */ "\033*r1A" ; /* Start raster graphics, rel. adressing */char *PCLEND = "\033*rB" /* end raster graphics */ "\033E" ; /* Printer reset. */void pclwrite ( OFILE *f, unsigned char *buf, int n ){ while ( n > 0 && buf [ n-1 ] == 0 ) n-- ; fprintf( f->f, "\033*b%dW", n ) ; fwrite ( buf, n, 1, f->f ) ;}/* Write a bit map as (raw) Portable Gray Map (PGM) format after decimating by a factor of 4. Sums bits in each 4x4-pel square to compute sample value. This function reduces each dimension of a bit map by 4 (it writes n*8/4 pixels per scan line and one scan line for every 4 in). The 17 possible sample values are spread linearly over the range 0-255. */void pgmwrite ( OFILE *f, u_char *buf, int n ){ static u_char gval [ MAXBITS * 8 / 4 ] ; static int init=0, lines=0 ; static u_char hbits [ 256 ] , lbits [ 256 ] ; static nybblecnt [ 16 ] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 } ; static u_char corr [ 17 ] = { 255, 239, 223, 207, 191, 175, 159, 143, 127, 111, 95, 79, 63, 47, 31, 15, 0 } ; int m ; u_char *p, *q ; if ( ! init ) { /* build table of bit counts in each nybble */ short i ; for ( i=0 ; i<256 ; i++ ) { hbits [ i ] = nybblecnt [ i >> 4 & 0x0f ] ; lbits [ i ] = nybblecnt [ i & 0x0f ] ; } init = 1 ; } for ( m=n, p=gval, q=buf ; m-- > 0 ; q++ ) { *p++ += hbits [ *q ] ; *p++ += lbits [ *q ] ; } if ( ( lines++ & 0x03 ) == 0x03 ) { for ( p=gval, m=2*n ; m-- > 0 ; p++ ) *p = corr [ *p ] ; fwrite ( gval, 1, 2*n, f->f ) ; memset ( gval, 0, 2*n ) ; }}/* Postscript image data is differentially coded vertically and run-length coded horizontally. A leading byte (n) defines the type of coding for subsequent data: 0 repeat previous line 1-127 n data bytes follow 128-254 copy n-127 bytes from previous line 255 n repeat the next character 'n' times The overhead for coding a copy is 2 bytes (copy count, data count), so copies > 2 bytes should be so coded. The overhead for coding a run is 4 bytes (255, count, byte, data count), so runs > 4 bytes should be so coded. Copies decode/execute faster and code more compactly so are preferred over runs.*/const char PSBEGIN [] = /* start of file */ "%%!PS-Adobe-2.0 EPSF-2.0 \n" "%%%%Creator: efax (Copyright 1995 Ed Casas) \n" "%%%%Title: efix output\n" "%%%%Pages: (atend) \n" "%%%%BoundingBox: 0 0 %d %d \n" "%%%%BeginComments \n" "%%%%EndComments \n" "/val 1 string def \n" "/buf %d string def \n" "/getval { \n" " currentfile val readhexstring pop 0 get \n" "} bind def \n" "/readbuf { \n" " 0 %% => index \n" " { \n" " dup buf length ge { exit } if \n" " getval %% => index run_length \n" " dup 127 le { \n" " dup 0 eq { \n" " pop buf length \n" " } { \n" " currentfile buf 3 index 3 index getinterval readhexstring pop pop\n" " } ifelse \n" " } { \n" " dup 255 eq { \n" " pop getval getval %% => index run_length value \n" " 2 index 1 3 index 2 index add 1 sub %% => ... start 1 end \n" " { buf exch 2 index put } for \n" " pop \n" " } { \n" " 127 sub \n" " } ifelse \n" " } ifelse \n" " add %% => index \n" " } loop \n" " pop \n" " buf \n" "} bind def \n" "%%%%EndProlog \n" ;const char PSPAGE [] = /* start of page */ "%%%%Page: %d %d \n" "gsave \n" "%f %f translate \n" "%f %f scale \n" "%d %d %d [ %d %d %d %d %d %d ] { readbuf } image \n" ;const char PSPAGEEND [] = /* end of page */ "\n" "grestore \n" "showpage \n" ;const char PSEND [] = /* end of file */ "%%Trailer \n" "%%%%Pages: %d \n" ;void psinit ( OFILE *f, int newfile, int page, int w, int h, int n ){ float ptw, pth ; ptw = w/f->xres * 72.0 ; /* convert to points */ pth = h/f->yres * 72.0 ; if ( newfile ) fprintf ( f->f, PSBEGIN, (int) ptw, (int) pth, /* Bounding Box */ n ) ; /* buffer string length */ fprintf ( f->f, PSPAGE, page, page, /* page number */ 0.0, 0.0, /* shift */ ptw, pth, /* scaling */ w, h, 1, /* image size */ w, 0, 0, -h, 0, h ) ; /* CTM */ f->firstpsline = newfile ; f->lastpageno = page ;}char nhexout = 0 , hexchars [ 16 ] = "0123456789abcdef" ;#define hexputc( f, c ) ( \ putc ( hexchars [ (c) >> 4 ] , f ), \ putc ( hexchars [ (c) & 0x0f ] , f ), \ ( ( ( nhexout++ & 31 ) == 31 ) ? putc ( '\n' , f ) : 0 ) )void hexputs ( FILE *f, u_char *p , int n ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -