home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / comm / misc / elcheapofax / rcs / fromfax.c,v < prev    next >
Text File  |  1993-12-21  |  15KB  |  762 lines

  1. head    1.5;
  2. access;
  3. symbols
  4.     OCT93:1.5;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.5
  10. date    93.10.25.02.14.27;    author Rhialto;    state Exp;
  11. branches;
  12. next    1.4;
  13.  
  14. 1.4
  15. date    93.09.18.22.41.27;    author Rhialto;    state Exp;
  16. branches;
  17. next    1.3;
  18.  
  19. 1.3
  20. date    93.08.20.03.45.27;    author Rhialto;    state Exp;
  21. branches;
  22. next    1.2;
  23.  
  24. 1.2
  25. date    93.06.11.16.33.37;    author Rhialto;    state Exp;
  26. branches;
  27. next    1.1;
  28.  
  29. 1.1
  30. date    93.06.11.14.53.53;    author Rhialto;    state Exp;
  31. branches;
  32. next    ;
  33.  
  34.  
  35. desc
  36. @Convert g3 data to bitmaps
  37. @
  38.  
  39.  
  40. 1.5
  41. log
  42. @Make +FBOR flexible; fix RTC detection bug.
  43. @
  44. text
  45. @/* Derived from: */
  46. /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
  47. **
  48. ** Copyright (C) 1989 by Paul Haeberli <paul@@manray.sgi.com>.
  49. **
  50. ** Permission to use, copy, modify, and distribute this software and its
  51. ** documentation for any purpose and without fee is hereby granted, provided
  52. ** that the above copyright notice appear in all copies and that both that
  53. ** copyright notice and this permission notice appear in supporting
  54. ** documentation.  This software is provided "as is" without express or
  55. ** implied warranty.
  56. */
  57. /* $Id: fromfax.c,v 1.4 1993/09/18 22:41:27 Rhialto Exp $
  58.  * $Log: fromfax.c,v $
  59.  * Revision 1.4  1993/09/18  22:41:27  Rhialto
  60.  * Improve on bit order terminology: use msb/lsb first.
  61.  *
  62.  * Revision 1.3  1993/08/20  03:45:27  Rhialto
  63.  * Add hack for auto-detecting fax bit order.
  64.  *
  65.  * Revision 1.2  1993/06/11  16:33:37  Rhialto
  66.  * First real RCS checkin
  67.  *
  68.  */
  69.  
  70. #include <stdio.h>
  71. #include <string.h>
  72. #include <ctype.h>
  73. #include "g3.h"
  74. #include "faxfile.h"
  75.  
  76. #ifdef DEBUG
  77. #define debug(x)    printf x
  78. #else
  79. #define debug(x)
  80. #endif
  81.  
  82. #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
  83. #define MAXCOLS LINE_BITS
  84. #define MAXROWS 4300        /* up to two pages long */
  85.  
  86. typedef struct faxin {
  87.     int     raw;
  88.     FAXHDR     faxhdr;
  89.     FAXHDR     pagehdr;
  90.     int     row;
  91.     int     endoffile;
  92.     int     eols;
  93.     int     rawzeros;
  94.     int     shdata;
  95.     int     shbit;
  96.     int     kludge;
  97.     int     reversebits;
  98.     int     stretch;
  99.     unsigned char  *bitp;
  100.     unsigned char    bitval;
  101.  
  102. } FAXIN;
  103.  
  104. static FAXIN faxin;
  105.  
  106. #define WHASHA 3510
  107. #define WHASHB 1178
  108.  
  109. #define BHASHA 293
  110. #define BHASHB 2695
  111.  
  112. #define HASHSIZE 1021
  113. static tableentry *whash[HASHSIZE];
  114. static tableentry *bhash[HASHSIZE];
  115.  
  116. static void addtohash(tableentry *hash[], tableentry* te, int n, int a, int b);
  117. static tableentry *hashfind(tableentry *hash[], int length, int code, int a, int b);
  118. static int getfaxrow(FILE *inf, int row, unsigned char *bitrow);
  119. static void skiptoeol(FILE *file);
  120. static int rawgetbit(FILE *file);
  121. extern int verbose;
  122.  
  123. int
  124. memisprint(unsigned char *s, int len)
  125. {
  126.     while (len > 0) {
  127.     if (s[0] && !isprint((s[0])))
  128.         return 0;
  129.     s++;
  130.     len--;
  131.     }
  132.     return 1;
  133. }
  134.  
  135. int
  136. try_line(FILE *ifp)
  137. {
  138.     int         col;
  139.     int         curlen,
  140.             curcode,
  141.             nextbit;
  142.     int         count,
  143.             color;
  144.     tableentry       *te;
  145.  
  146.     col = 0;
  147.     curlen = 0;
  148.     curcode = 0;
  149.     color = 1;        /* 1=white, 0=black */
  150.     count = 0;
  151.  
  152.     while (!faxin.endoffile) {
  153.     if (col >= MAXCOLS) {
  154.         skiptoeol(ifp);
  155.         return col;
  156.     }
  157.     do {
  158.         if (faxin.rawzeros >= 11) {
  159.         nextbit = rawgetbit(ifp);
  160.         if (nextbit) {
  161.             if (col && col < LINE_BITS)
  162.             return -1;
  163.             return (col);
  164.         }
  165.         if (feof(ifp)) {
  166.             return -1;
  167.         }
  168.         } else
  169.         nextbit = rawgetbit(ifp);
  170.         curcode = (curcode << 1) + nextbit;
  171.         curlen++;
  172.     } while (curcode <= 0);
  173.     if (curlen > 13) {
  174.         skiptoeol(ifp);
  175.         return -1;
  176.     }
  177.     if (color) {
  178.         if (curlen < 4)
  179.         continue;
  180.         te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  181.     } else {
  182.         if (curlen < 2)
  183.         continue;
  184.         te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  185.     }
  186.     if (!te)
  187.         continue;
  188.     switch (te->tabid) {
  189.     case TWTABLE:
  190.     case TBTABLE:
  191.         count += te->count;
  192.         if (col + count > MAXCOLS)
  193.         count = MAXCOLS - col;
  194.         if (count > 0) {
  195.         col += count;
  196.         count = 0;
  197.         }
  198.         curcode = 0;
  199.         curlen = 0;
  200.         color = !color;
  201.         break;
  202.     case MWTABLE:
  203.     case MBTABLE:
  204.         count += te->count;
  205.         curcode = 0;
  206.         curlen = 0;
  207.         break;
  208.     case EXTABLE:
  209.         count += te->count;
  210.         curcode = 0;
  211.         curlen = 0;
  212.         break;
  213.     default:
  214.         fprintf(stderr, "internal bad poop\n");
  215.     }
  216.     }
  217. }
  218.  
  219. int
  220. infer_bitorder(FILE *f)
  221. {
  222.     int         normerrors = 0;
  223.     int         reverrors = 0;
  224.     int         i;
  225.     long        pos;
  226.  
  227.     pos = ftell(f);
  228.  
  229.     if (verbose)
  230.     printf("try MSB first...");
  231.     faxin.reversebits = 0;
  232.     faxin.shbit = 0;
  233.     skiptoeol(f);
  234.     for (i = 0; i < 10; i++)
  235.     if (try_line(f) == -1)
  236.         normerrors++;
  237.     fseek(f, pos, SEEK_SET);
  238.     if (verbose)
  239.     printf(" %d errors\n", normerrors);
  240.  
  241.     if (verbose)
  242.     printf("try LSB first...");
  243.     faxin.reversebits = 1;
  244.     faxin.shbit = 0;
  245.     skiptoeol(f);
  246.     for (i = 0; i < 10; i++)
  247.     if (try_line(f) == -1)
  248.         reverrors++;
  249.     fseek(f, pos, SEEK_SET);
  250.     if (verbose)
  251.     printf(" %d errors\n", reverrors);
  252.  
  253.     if (normerrors < reverrors) {
  254.     return faxin.reversebits = 0;
  255.     } else {
  256.     fprintf(stderr, "Warning: this file has its bits the wrong way!\n");
  257.     return faxin.reversebits = 1;
  258.     }
  259. }
  260.  
  261. /*
  262.  * Prepare for reading a faxfile.
  263.  * dostretch (ignored) indicates we must repeat each scan line.
  264.  * bitorder indicates bit order: 0=normal: lsb first, 1=reversed: msb first.
  265.  *                 -1: auto-detect.
  266.  *    For understandable reasons, the designer of this decoder had
  267.  *    the opposite idea of what was normal and reversed, hence
  268.  *    some confusion.
  269.  */
  270.  
  271. long    /* error code */
  272. faxin_open_fp(FILE *ifp, int dostretch, int bitorder)
  273. {
  274.     int         i;
  275.  
  276.     faxin.stretch = dostretch;
  277.  
  278.     for (i = 0; i < HASHSIZE; ++i)
  279.     whash[i] = bhash[i] = (tableentry *) 0;
  280.     addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB);
  281.     addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB);
  282.     addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB);
  283.     addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB);
  284.     addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB);
  285.     addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB);
  286.  
  287. #ifdef _DCC
  288.     setvbuf(ifp, NULL, _IOFBF, 16384);
  289. #endif
  290.     /* Attempt to read file/page header */
  291.     if (fread(&faxin.faxhdr, sizeof(faxin.faxhdr), 1, ifp) == 1) {
  292.     fseek(ifp, -sizeof(faxin.faxhdr), SEEK_CUR);
  293. #if 1
  294.     faxin.raw = 1;
  295. #else
  296.     faxin.raw = !memisprint(&faxin.faxhdr.id.magic[0], sizeof(faxin.faxhdr.id.magic));
  297.     debug(("assume faxin.raw = %d\n", faxin.raw));
  298. #endif
  299.     /* If fax is raw, try to infer bit order */
  300.     if (faxin.raw) {
  301.         faxin.reversebits = !bitorder;    /* swap 0 and 1 */
  302.         if (bitorder < 0)
  303.         bitorder = infer_bitorder(ifp);
  304.         if (bitorder < 0) {
  305.         debug(("fail on bit order\n"));
  306.         return 1;
  307.         }
  308.     }
  309.  
  310.     return 0;
  311.     }
  312.     fprintf(stderr, "file too short\n");
  313.  
  314.     return 1;
  315. }
  316.  
  317. int
  318. faxin_begin_page(FILE *ifp)
  319. {
  320.     if (faxin.raw && ftell(ifp) != 0) {
  321.     /* Raw files contain only one page and no header */
  322.     return 1;
  323.     }
  324.  
  325.     if (faxin.raw == 0) {
  326.     int        bytes;
  327.     int        byte;
  328.  
  329.     /* Skip past page header by finding magic id */
  330.     retry:
  331.     bytes = 0;
  332.     /* Shortcut for first byte */
  333.     while ((byte = getc(ifp)) != faxin.faxhdr.id.magic[0]) {
  334.         if (feof(ifp)) {
  335.         return 1;
  336.         }
  337.     }
  338.     faxin.pagehdr.id.magic[0] = byte;
  339.     bytes = 1;
  340.  
  341.     while (bytes < sizeof(faxin.faxhdr.id)) {
  342.         /* Do we have a matching prefix? */
  343.         if (memcmp(faxin.pagehdr.id.magic, faxin.faxhdr.id.magic, bytes) == 0) {
  344.         /* Yes, read one more byte and continue */
  345.         byte = getc(ifp);
  346.         if (feof(ifp))
  347.             return 1;
  348.         faxin.pagehdr.id.magic[bytes] = byte;
  349.         bytes++;
  350.         } else {
  351.         /* Shift everything down and reduce match length */
  352.         bytes--;
  353.         if (bytes == 0)
  354.             goto retry;
  355.         memmove(faxin.pagehdr.id.magic, faxin.pagehdr.id.magic + 1, bytes);
  356.         }
  357.     }
  358.  
  359.     fread(&faxin.pagehdr.info, sizeof(faxin.pagehdr) - sizeof(faxin.pagehdr.id), 1, ifp);
  360.     if (feof(ifp)) {
  361.         fprintf(stderr, "Premature EOF after header\n");
  362.         return 1;
  363.     }
  364.  
  365.     /* "Normal" bit ordering is MSB first */
  366.     faxin.reversebits = !faxin.pagehdr.info.msbfirst;
  367.     }
  368.  
  369.     faxin.eols = 0;
  370.     faxin.rawzeros = 0;
  371.     faxin.endoffile = 0;
  372.     faxin.row = 0;
  373.     faxin.shbit = 0;
  374.  
  375.     if (faxin.raw && feof(ifp)) {
  376.     return 1;
  377.     }
  378.  
  379. #ifdef KLUDGE
  380.     if (faxin.kludge) {
  381.     /* Skip extra lines to get in sync. */
  382.     skiptoeol(ifp);
  383.     skiptoeol(ifp);
  384.