📄 efaxlib.c.orig
字号:
/* efaxlib.c - utility routines for efax Copyright 1995 Ed Casas*/#include <ctype.h>#include <stdio.h>#include <string.h>#include "efaxmsg.h"#include "efaxlib.h"#ifndef SEEK_SET#define SEEK_SET 0#endif#define DEFXRES 204.145 /* fax x and y resolution in dpi */#define DEFYRES 195.58#define DEFWIDTH 1728 /* 215x297 mm image at fax resolution */#define DEFHEIGHT 2287extern t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] ; /* T.4 coding tables */extern t4tab btab [ ( 64 + 27 + 13 ) + 1 ] ;short short256 = 256 ; /* for endian-ness detection *//* Make sure printf strings have only %d escapes and n or fewer of them. Returns 0 if OK, 1 on error. */int ckfmt ( char *p, int n ){ for ( ; *p ; p++ ) { if ( p[0] == '%' ) { if ( p[1] == 'd' ) n-- ; else if ( p[1] == '%' ) p++ ; else n=-1 ; } } return n < 0 ;}/* Initialize state of variable-length code word encoder. */void newENCODER ( ENCODER *e ){ e->x = 0 ; e->shift = -8 ;}/* Store a code word `code' of length `bits' (<=24) in buffer pointed to by `buf'. Bits that don't fit in complete bytes are saved between calls. To flush the remaining bits call the function with code=0 and bits=0. Returns pointer to next free element in output buffer. Calling function must ensure at least bits/8 bytes are available in buffer. */uchar *putcode ( ENCODER *e, short code, short bits, uchar *buf ){ e->x = ( e->x << bits ) | code ; e->shift += bits ? bits : -e->shift ; while ( e->shift >= 0 ) { *buf++ = e->x >> e->shift ; e->shift -= 8 ; } return buf ;}/* Convert run lengths to 1-D T.4-codes. First run is white. Silently truncates run lengths that are too long. After using this function EOLs may need to be added and/or the putcode() buffer flushed. Returns pointer to next free element in output buffer. */uchar *runtocode ( ENCODER *e, short *runs, int nr, uchar *codes ){ uchar col = 0, *maxcodes = codes + MAXCODES ; t4tab *ctab = wtab, *p ; short rlen ; long x ; short shift ;#define PUTCODE(p) { x = ( x << p->bits ) | p->code ; shift += p->bits ; \ while ( shift >= 0 ) { *codes++ = x >> shift ; shift -= 8 ; } } x = e->x ; shift = e->shift ; while ( nr-- > 0 ) { rlen = *runs++ ; if ( rlen > 63 ) { /* make-up code */ if ( rlen > MAXRUNLEN ) rlen = MAXRUNLEN ; p = ctab + 63 + ( rlen >> 6 ) ; if ( codes < maxcodes ) PUTCODE(p) ; } p = ctab + ( rlen & 0x3f ) ; /* terminating code */ if ( codes < maxcodes ) PUTCODE(p) ; ctab = ( col ^= 1 ) ? btab : wtab ; } e->x = x ; e->shift = shift ; return codes ;}/* Pad/truncate run-length coded scan line 'runs' of 'nr' runs by 'pad' pixels (truncate if negative). Returns the new number of runs. */int xpad ( short *runs, int nr, int pad ){ if ( pad < 0 ) { /* truncate */ while ( pad < 0 ) pad += ( nr <= 0 ? -pad : runs [ --nr ] ) ; runs [ nr++ ] = pad ; } else { /* pad with white */ if ( nr & 1 ) runs [ nr - 1 ] += pad ; else runs [ nr++ ] = pad ; } return nr ;}/* Shift a run-length coded scan line right by s pixels (left if negative). If necessary, zero-length runs are created to avoid copying. Returns the pixel width change (+/-). */int xshift ( short *runs, int nr, int s ){ int i=0, n=0 ; if ( s < 0 ) { for ( i = 0 ; s < 0 && i < nr ; i++ ) { s += runs [ i ] ; n -= runs [ i ] ; runs [ i ] = 0 ; } i-- ; } if ( i < nr ) { runs [ i ] += s ; n += s ; } return n ;}/* Scale nr run lengths in buffer pointed to by p to scale image horizontally. The scaling factor is xs/256. Returns new line width in pixels. */int xscale ( short *p, int nr, int xs ){ int inlen=0, outlen=0 ; for ( ; nr-- > 0 ; p++ ) { inlen += *p ; *p = ( ( inlen * xs + 128 ) >> 8 ) - outlen ; outlen += *p ; } return outlen ;}/* Invert a run-length buffer by prepending or removing a zero-length initial run. */int xinvert ( short *p, int nr ){ int i ; if ( ! *p ) { for ( i=0 ; i<nr-1 ; i++ ) { /* remove */ p[i] = p[i+1] ; } nr-- ; } else { for ( i=nr ; i>0 ; i-- ) { /* insert */ p[i] = p[i-1] ; } p[0] = 0 ; nr++ ; } return nr ;}/* Zero-terminated lists of run lengths for each byte. */uchar byteruns [ 1408 + 1 ] = "8071061106205120511105210530413041210411110411204220421104310440" "3140313103121103122031112031111103112103113032303221032111032120" "3320331103410350215021410213110213202121202121110212210212302111" "3021112102111111021111202112202112110211310211402240223102221102" "2220221120221111022121022130233023210231110231202420241102510260" "1160115101141101142011312011311101132101133011213011212101121111" "0112112011222011221101123101124011114011113101111211011112201111" "1120111111110111112101111130111230111221011121110111212011132011" "1311011141011150125012410123110123201221201221110122210122301211" "3012112101211111012111201212201212110121310121401340133101321101" "3220131120131111013121013130143014210141110141201520151101610170" "1701610151101520141201411101421014301313013121013111101311201322" "0132110133101340121401213101212110121220121112012111110121121012" "1130122301222101221110122120123201231101241012501115011141011131" "1011132011121201112111011122101112301111130111112101111111101111" "1120111122011112110111131011114011240112310112211011222011211201" "1211110112121011213011330113210113111011312011420114110115101160" "2602510241102420231202311102321023302213022121022111102211202222" "0222110223102240211402113102112110211220211112021111110211121021" "1130212302122102121110212120213202131102141021503503410331103320" "3212032111032210323031130311210311111031112031220312110313103140" "4404310421104220411204111104121041305305210511105120620611071080" ;/* Convert byte-aligned bit-mapped n-byte scan line into array of run lengths. Run length array must have *more* than 8*n elements. First run is white. Returns number of runs coded. */int bittorun ( uchar *bits, int n, short *runs ){ static uchar init=0, *rltab [ 256 ] ; register uchar *p, c, lastc = 0x00 ; short *runs0 = runs ; if ( ! init ) { /* initialize pointer and run tables */ int i = 0 ; for ( rltab[ 0 ] = p = byteruns ; *p ; p++ ) if ( ! ( *p -= '0' ) && i < 255 ) rltab [ ++i ] = p+1 ; init = 1 ; } *runs = 0 ; for ( ; n > 0 ; n-- ) { p = rltab [ c = *bits++ ] ; if ( ( lastc & 0x01 ) ? ! ( c & 0x80 ) : ( c & 0x80 ) ) *(++runs) = *p++ ; /* new run */ else *runs += *p++ ; /* continue run */ while ( *p ) *(++runs) = *p++ ; lastc = c ; } return runs - runs0 + 1 ;}/* Bitwise-OR two run-length coded scan lines. The run length vectors a and b are OR-ed into c. If c is null, the result is placed in a. The new image width is stored in pels if it is not null. Returns the number of runs in the result. */int runor ( short *a, int na, short *b, int nb, short *c, int *pels ){ register short la, lb ; int ia, ib, ic, np=0 ; short tmp [ MAXRUNS ] ; if ( ! c ) c = tmp ; la = a [ ia = 0 ] ; lb = b [ ib = 0 ] ; c [ ic = 0 ] = 0 ; while ( 1 ) { if ( la <= lb ) { /* select shorter sub-run */ if ( ( ( ia | ib ) ^ ic ) & 1 ) /* OR of subruns same colour as c? */ c [ ++ic ] = la ; /* no, new output run */ else c [ ic ] += la ; /* yes, add it */ lb -= la ; /* align subruns */ if ( ++ia >= na ) break ; /* done */ la = a [ ia ] ; /* get new subrun */ } else { /* same for line b ... */ if ( ( ( ia | ib ) ^ ic ) & 1 ) c [ ++ic ] = lb ; else c [ ic ] += lb ; la -= lb ; if ( ++ib >= nb ) break ; lb = b [ ib ] ; } } if ( ia < na ) while ( 1 ) { if ( ( ia ^ ic ) & 1 ) c [ ++ic ] = la ; else c [ ic ] += la ; if ( ++ia >= na ) break ; la = a [ ia ] ; } else while ( 1 ) { if ( ( ib ^ ic ) & 1 ) c [ ++ic ] = lb ; else c [ ic ] += lb ; if ( ++ib >= nb ) break ; lb = b [ ib ] ; } if ( c == tmp ) for ( ia=0 ; ia <= ic ; ia++ ) np += a[ia] = c[ia] ; if ( pels ) *pels = np ; return ic + 1 ;} /* Get a number from a PBM file header while skipping whitespace and comments. Returns the number or 0 on EOF. Reads one more byte than used by the number. */int pbmdim ( IFILE *f ){ int c, n=0 ; /* scan for first digit and skip comments */ while ( ! isdigit ( c = fgetc ( f->f ) ) && c >= 0 ) if ( c == '#' ) while ( ( c = fgetc ( f->f ) ) != '\n' && c >= 0 ) ; /* get the number */ if ( c >= 0 && isdigit( c ) ) { n = c - '0' ; while ( isdigit ( c = fgetc ( f->f ) ) && c >= 0 ) n = n * 10 + c - '0' ; } return n ;}/* Append nb bits from in[from] to bit-mapped scan line buffer where `from' is a bit (not byte) index. Bits in bytes are ordered from MS to LS bit. Initialize before each scan line by calling with nb=0 and in pointing to output buffer. Flush 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 ( uchar *in, int from, short nb ){ uchar *f ; short bits ; static uchar *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'. The font is scaled so it appears to have cells of width w and height h. lmargin pixels of white space are added at the left margin. Sets 'pels' to line width if not null. Returns number of runs coded. */int texttorun ( uchar *txt, faxfont *font, short line, int w, int h, int lmargin, short *runs, int *ppels ){ uchar *in, out [ MAXLINELEN * MAXFONTW / 8 + 1 ] ; int i, nc = 0, cw, nr, pels ; line = ( line * font->h + h/2 ) / h ; 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 ) ; nr = bittorun ( out, ( nc*cw + 7 )/8, runs ) ; if ( font->w == w ) pels = nc*cw ; else pels = xscale ( runs, nr, ( w * 256 ) / font->w ) ; pels += xshift ( runs, nr, lmargin ) ; if ( ppels ) *ppels = pels ; return nr ;} /* Image File Input Functions *//* Names of file formats */char *iformatname [ NIFORMATS ] = IFORMATS ;char *oformatname [ NOFORMATS ] = OFORMATS ;char *pformatname [ NPFORMATS ] = PFORMATS ;/* Log the names of files still to be sent using the "msg()" format string s. */void logifnames ( IFILE *f, char *s ){ PAGE *p ; char *fn ; if ( f && f->page ) for ( p = f->page ; p <= f->lastpage ; p++ ) { fn = p->fname ; if ( fn ) msg ( s, fn ) ; }}/* Read run lengths for one scan line from T.4-coded IFILE f into buffer runs. 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 ( IFILE *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 ; DECODER *d ; uchar reverse=f->page->revbits ; maxp = ( p = runs ) + MAXRUNS ; d = &f->d ; x = d->x ; shift = d->shift ; tab = d->tab ; /* restore decoder state */ do { do { while ( shift < 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -