/* pbmtog3.c - read a portable bitmap and produce a Group 3 FAX file ** ** Copyright (C) 1989 by Paul Haeberli . ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include "pbm.h" #include "shhopt.h" #include "g3.h" static int reversebits; struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char *inputFilespec; /* Filespec of input file */ unsigned int reversebits; unsigned int nofixedwidth; unsigned int verbose; }; static int shdata; static int shbit; static void parseCommandLine(int argc, char ** const argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ optEntry *option_def = malloc(100*sizeof(optEntry)); /* Instructions to OptParseOptions2 on how to parse our options. */ optStruct3 opt; unsigned int option_def_index; option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "reversebits", OPT_FLAG, NULL, &cmdlineP->reversebits, 0); OPTENT3(0, "nofixedwidth", OPT_FLAG, NULL, &cmdlineP->nofixedwidth, 0); OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = TRUE; /* We may have parms that are negative numbers */ optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc-1 == 0) cmdlineP->inputFilespec = "-"; else if (argc-1 != 1) pm_error("Program takes zero or one argument (filename). You " "specified %d", argc-1); else cmdlineP->inputFilespec = argv[1]; } static void putbit(d) int d; { if(d) shdata = shdata|shbit; if ( reversebits ) shbit = shbit<<1; else shbit = shbit>>1; if((shbit&0xff) == 0) { putchar(shdata); shdata = 0; shbit = reversebits ? 0x01 : 0x80; } } static void flushbits( ) { if ( ( reversebits && shbit != 0x01 ) || ( ! reversebits && shbit != 0x80 ) ) { putchar(shdata); shdata = 0; shbit = reversebits ? 0x01 : 0x80; } } static void putcode(te) tableentry* te; { unsigned int mask; int code; mask = 1<<(te->length-1); code = te->code; while(mask) { if(code&mask) putbit(1); else putbit(0); mask >>= 1; } } static void puteol() { int i; for(i=0; i<11; ++i) putbit(0); putbit(1); } static void putblackspan(int c); static void putwhitespan(c) int c; { int tpos; tableentry* te; do { if(c>=64) { if (c < 1792) { tpos = (c - 64) / 64; te = mwtable+tpos; } else { tpos = (c - 1792) / 64; if (tpos > ((2560 - 1792) / 64)) tpos = (2560 - 1792) / 64; te = extable+tpos; } c -= te->count; putcode(te); } tpos = c; if (tpos >= 64) tpos = 63; te = twtable+tpos; c -= te->count; putcode(te); if (c) putblackspan(0); } while (c); } static void putblackspan(c) int c; { int tpos; tableentry* te; do { if(c>=64) { if (c < 1792) { tpos = (c - 64) / 64; te = mbtable+tpos; } else { tpos = (c - 1792) / 64; if (tpos > ((2560 - 1792) / 64)) tpos = (2560 - 1792) / 64; te = extable+tpos; } c -= te->count; putcode(te); } tpos = c; if (tpos >= 64) tpos = 63; te = tbtable+tpos; c -= te->count; putcode(te); if (c) putwhitespan(0); } while (c); } static void tofax(bitrow,n) bit* bitrow; int n; { int c; while(n>0) { c = 0; while(*bitrow == PBM_WHITE && n>0) { ++bitrow; ++c; --n; } putwhitespan(c); c = 0; if(n==0) break; while(*bitrow == PBM_BLACK && n>0) { ++bitrow; ++c; --n; } putblackspan(c); } puteol(); } static void putinit() { shdata = 0; shbit = reversebits ? 0x01 : 0x80; } int main( argc, argv ) int argc; char* argv[]; { struct cmdlineInfo cmdline; FILE* ifP; bit* bitrow; int rows, cols, bigcols, format, row, i; pbm_init( &argc, argv ); parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.inputFilespec); reversebits = cmdline.reversebits; pbm_readpbminit( ifP, &cols, &rows, &format ); if (cmdline.nofixedwidth) bigcols = cols; else bigcols = 1728; bitrow = pbm_allocrow( MAX( cols, bigcols ) ); /* Write out four extra rows to get things stabilized. */ putinit(); puteol(); /* Write out bitmap. */ for ( row = 0; row < rows; ++row ) { for ( i = cols; i < bigcols; i ++ ) bitrow[i] = PBM_WHITE; pbm_readpbmrow( ifP, bitrow, cols, format ); tofax( bitrow, bigcols ); } /* And finish off. */ for( i = 0; i < 6; ++i ) puteol( ); flushbits( ); pm_close( ifP ); exit( 0 ); }