home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsm / netpbmsca / pbm / c / g3topbm < prev    next >
Encoding:
Text File  |  1993-12-07  |  6.4 KB  |  314 lines

  1. /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
  2. **
  3. ** Copyright (C) 1989 by Paul Haeberli <paul@manray.sgi.com>.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14. #include "g3.h"
  15.  
  16. #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
  17. #define MAXCOLS 1728
  18. #define MAXROWS 4300    /* up to two pages long */
  19.  
  20. static int endoffile = 0;
  21. static int eols;
  22. static int rawzeros;
  23. static int shdata;
  24. static int kludge;
  25. static int reversebits;
  26. static int stretch;
  27.  
  28. #define WHASHA 3510
  29. #define WHASHB 1178
  30.  
  31. #define BHASHA 293
  32. #define BHASHB 2695
  33.  
  34. #define HASHSIZE 1021
  35. static tableentry* whash[HASHSIZE];
  36. static tableentry* bhash[HASHSIZE];
  37.  
  38. static void addtohash ARGS(( tableentry* hash[], tableentry* te, int n, int a, int b ));
  39. static tableentry* hashfind ARGS(( tableentry* hash[], int length, int code, int a, int b ));
  40. static int getfaxrow ARGS(( FILE* inf, int row, bit* bitrow ));
  41. static void skiptoeol ARGS(( FILE* file ));
  42. static int rawgetbit ARGS(( FILE* file ));
  43.  
  44. static bit* bits[MAXROWS];
  45.  
  46. int
  47. main( argc, argv )
  48.     int argc;
  49.     char* argv[];
  50.     {
  51.     FILE* ifp;
  52.     int argn, rows, cols, row, col, i;
  53.     char* usage = "[-kludge][-reversebits][-stretch] [g3file]";
  54.  
  55.  
  56.     pbm_init( &argc, argv );
  57.  
  58.     argn = 1;
  59.     kludge = 0;
  60.     reversebits = 0;
  61.     stretch = 0;
  62.  
  63.     /* Check for flags. */
  64.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  65.     {
  66.     if ( pm_keymatch( argv[argn], "-kludge", 2 ) )
  67.         kludge = 1;
  68.     else if ( pm_keymatch( argv[argn], "-reversebits", 2 ) )
  69.         reversebits = 1;
  70.     else if ( pm_keymatch( argv[argn], "-stretch", 2 ) )
  71.         stretch = 1;
  72.     else
  73.         pm_usage( usage );
  74.     argn++;
  75.     }
  76.  
  77.     if ( argn < argc )
  78.     {
  79.     ifp = pm_openr( argv[argn] );
  80.     argn++;
  81.     }
  82.     else
  83.     ifp = stdin;
  84.  
  85.     if ( argn != argc )
  86.     pm_usage( usage );
  87.  
  88.     eols = 0;
  89.  
  90.     if ( kludge )
  91.     {
  92.     /* Skip extra lines to get in sync. */
  93.     skiptoeol( ifp );
  94.     skiptoeol( ifp );
  95.     skiptoeol( ifp );
  96.     }
  97.     skiptoeol( ifp );
  98.     for ( i = 0; i < HASHSIZE; ++i )
  99.     whash[i] = bhash[i] = (tableentry*) 0;
  100.     addtohash( whash, twtable, TABSIZE(twtable), WHASHA, WHASHB );
  101.     addtohash( whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB );
  102.     addtohash( whash, extable, TABSIZE(extable), WHASHA, WHASHB );
  103.     addtohash( bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB );
  104.     addtohash( bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB );
  105.     addtohash( bhash, extable, TABSIZE(extable), BHASHA, BHASHB );
  106.  
  107.     cols = 0;
  108.     for ( rows = 0; rows < MAXROWS; ++rows )
  109.     {
  110.     bits[rows] = pbm_allocrow( MAXCOLS );
  111.     col = getfaxrow( ifp, rows, bits[rows] );
  112.     if ( endoffile )
  113.         break;
  114.     if ( col > cols )
  115.         cols = col;
  116.     if ( stretch )
  117.         {
  118.         bits[rows + 1] = bits[rows];
  119.         ++rows;
  120.         }
  121.     }
  122.  
  123.     pm_close( ifp );
  124.  
  125.     pbm_writepbminit( stdout, cols, rows, 0 );
  126.     for ( row = 0; row < rows; ++row )
  127.     pbm_writepbmrow( stdout, bits[row], cols, 0 );
  128.     pm_close( stdout );
  129.  
  130.     exit(0);
  131.     }
  132.  
  133. static void
  134. addtohash(hash, te, n, a, b)
  135.     tableentry* hash[];
  136.     tableentry* te;
  137.     int n, a, b;
  138. {
  139.     unsigned int pos;
  140.  
  141.     while (n--) {
  142.         pos = ((te->length+a)*(te->code+b))%HASHSIZE;
  143.         if (hash[pos] != 0)
  144.             pm_error( "internal error: addtohash fatal hash collision" );
  145.         hash[pos] = te;
  146.         te++;
  147.     }
  148. }
  149.  
  150. static tableentry*
  151. hashfind(hash, length, code, a, b)
  152.     tableentry* hash[];
  153.     int length, code;
  154.     int a, b;
  155.     {
  156.     unsigned int pos;
  157.     tableentry* te;
  158.  
  159.     pos = ((length+a)*(code+b))%HASHSIZE;
  160.     if (pos < 0 || pos >= HASHSIZE)
  161.     pm_error(
  162.         "internal error: bad hash position, length %d code %d pos %d",
  163.         length, code, pos );
  164.     te = hash[pos];
  165.     return ((te && te->length == length && te->code == code) ? te : 0);
  166.     }
  167.  
  168. static int
  169. getfaxrow( inf, row, bitrow )
  170.     FILE* inf;
  171.     int row;
  172.     bit* bitrow;
  173. {
  174.     int col;
  175.     bit* bP;
  176.     int curlen, curcode, nextbit;
  177.     int count, color;
  178.     tableentry* te;
  179.  
  180.     for ( col = 0, bP = bitrow; col < MAXCOLS; ++col, ++bP )
  181.         *bP = PBM_WHITE;
  182.     col = 0;
  183.     rawzeros = 0;
  184.     curlen = 0;
  185.     curcode = 0;
  186.     color = 1;
  187.     count = 0;
  188.     while (!endoffile) {
  189.         if (col >= MAXCOLS) {
  190.             skiptoeol(inf);
  191.             return (col); 
  192.         }
  193.         do {
  194.             if (rawzeros >= 11) {
  195.                 nextbit = rawgetbit(inf);
  196.                 if (nextbit) {
  197.                     if (col == 0)
  198.                         /* XXX should be 6 */
  199.                         endoffile = (++eols == 3);
  200.                     else
  201.                         eols = 0;
  202. #ifdef notdef
  203.                     if (col && col < 1728)
  204.                         pm_message(
  205.                            "warning, row %d short (len %d)",
  206.                             row, col );
  207. #endif /*notdef*/
  208.                     return (col); 
  209.                 }
  210.             } else
  211.                 nextbit = rawgetbit(inf);
  212.             curcode = (curcode<<1) + nextbit;
  213.             curlen++;
  214.         } while (curcode <= 0);
  215.         if (curlen > 13) {
  216.             pm_message(
  217.       "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL",
  218.                 row, col, curlen, curcode, 0 );
  219.             skiptoeol(inf);
  220.             return (col);
  221.         }
  222.         if (color) {
  223.             if (curlen < 4)
  224.                 continue;
  225.             te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  226.         } else {
  227.             if (curlen < 2)
  228.                 continue;
  229.             te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  230.         }
  231.         if (!te)
  232.             continue;
  233.         switch (te->tabid) {
  234.         case TWTABLE:
  235.         case TBTABLE:
  236.             count += te->count;
  237.             if (col+count > MAXCOLS) 
  238.                 count = MAXCOLS-col;
  239.             if (count > 0) {
  240.                 if (color) {
  241.                     col += count;
  242.                     count = 0;
  243.                 } else {
  244.                     for ( ; count > 0; --count, ++col )
  245.                         bitrow[col] = PBM_BLACK;
  246.                 }
  247.             }
  248.             curcode = 0;
  249.             curlen = 0;
  250.             color = !color;
  251.             break;
  252.         case MWTABLE:
  253.         case MBTABLE:
  254.             count += te->count;
  255.             curcode = 0;
  256.             curlen = 0;
  257.             break;
  258.         case EXTABLE:
  259.             count += te->count;
  260.             curcode = 0;
  261.             curlen = 0;
  262.             break;
  263.         default:
  264.             pm_error( "internal bad poop" );
  265.         }
  266.     }
  267.     return (0);
  268. }
  269.  
  270. static void
  271. skiptoeol( file )
  272.     FILE* file;
  273.     {
  274.     while ( rawzeros < 11 )
  275.     (void) rawgetbit( file );
  276.     for ( ; ; )
  277.     {
  278.     if ( rawgetbit( file ) )
  279.         break;
  280.     }
  281.     }
  282.  
  283. static int shbit = 0;
  284.  
  285. static int
  286. rawgetbit( file )
  287.     FILE* file;
  288.     {
  289.     int b;
  290.  
  291.     if ( ( shbit & 0xff ) == 0 )
  292.     {
  293.     shdata = getc( file );
  294.     if ( shdata == EOF )
  295.         pm_error( "EOF / read error at line %d", eols );
  296.     shbit = reversebits ? 0x01 : 0x80;
  297.     }
  298.     if ( shdata & shbit )
  299.     {
  300.     rawzeros = 0;
  301.     b = 1;
  302.     }
  303.     else
  304.     {
  305.     rawzeros++;
  306.     b = 0;
  307.     }
  308.     if ( reversebits )
  309.     shbit <<= 1;
  310.     else
  311.     shbit >>= 1;
  312.     return b;
  313.     }
  314.