home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / 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.     skiptoeol(ifp);
  385.     }
  386. #endif
  387.     skiptoeol(ifp);
  388.     if (feof(ifp)) {
  389.     return 1;
  390.     }
  391.  
  392.     return 0;
  393. }
  394.  
  395. static void
  396. addtohash(hash, te, n, a, b)
  397. tableentry     *hash[];
  398. tableentry     *te;
  399. int        n,
  400.         a,
  401.         b;
  402.  
  403. {
  404.     unsigned int    pos;
  405.  
  406.     while (n--) {
  407.     pos = ((te->length + a) * (te->code + b)) % HASHSIZE;
  408.     if (hash[pos] != 0)
  409.         fprintf(stderr, "internal error: addtohash fatal hash collision\n");
  410.     hash[pos] = te;
  411.     te++;
  412.     }
  413. }
  414.  
  415. static tableentry *
  416. hashfind(hash, length, code, a, b)
  417. tableentry     *hash[];
  418. int        length,
  419.         code;
  420. int        a,
  421.         b;
  422.  
  423. {
  424.     unsigned int    pos;
  425.     tableentry       *te;
  426.  
  427.     pos = ((length + a) * (code + b)) % HASHSIZE;
  428.     if (pos >= HASHSIZE)
  429.     fprintf(stderr,
  430.        "internal error: bad hash position, length %d code %d pos %d\n",
  431.          length, code, pos);
  432.     te = hash[pos];
  433.     return ((te && te->length == length && te->code == code) ? te : 0);
  434. }
  435.  
  436. /* Put some black (color 1) bits in IFF bitmap format */
  437. void
  438. putblackbits(int count)
  439. {
  440.     while (count > 0) {
  441.     *faxin.bitp |= faxin.bitval;    /* Set a single bit */
  442.     count--;
  443.     faxin.bitval >>= 1;
  444.     if (faxin.bitval == 0) {
  445.         faxin.bitval = 0x80;
  446.         faxin.bitp++;
  447.         /* While we're byte-aligned, do 8 bits at a time */
  448.         while (count >= 8) {
  449.         *faxin.bitp++ = 0xFF;
  450.         count -= 8;
  451.         }
  452.     }
  453.     }
  454. }
  455.  
  456. /* Put some white (color 0) bits in IFF bitmap format */
  457. void
  458. putwhitebits(int count)
  459. {
  460.     while (count > 0) {
  461.     /* don't set a bit */
  462.     count--;
  463.     faxin.bitval >>= 1;
  464.     if (faxin.bitval == 0) {
  465.         faxin.bitval = 0x80;
  466.         faxin.bitp++;
  467.         /* While we're byte-aligned, do 8 bits at a time */
  468.         while (count >= 8) {
  469.         faxin.bitp++;
  470.         count -= 8;
  471.         }
  472.     }
  473.     }
  474. }
  475.  
  476. int
  477. fromfax(ifp, bitrow)
  478. FILE           *ifp;
  479. unsigned char *bitrow;
  480. {
  481.     int         col;
  482.     int         curlen,
  483.             curcode,
  484.             nextbit;
  485.     int         count,
  486.             color;
  487.     tableentry       *te;
  488.  
  489.     col = 0;
  490.     curlen = 0;
  491.     curcode = 0;
  492.     color = 1;        /* 1=white, 0=black */
  493.     count = 0;
  494.     faxin.bitp = bitrow;
  495.     faxin.bitval = 0x80;
  496.     faxin.row++;
  497.  
  498.     while (!faxin.endoffile) {
  499.     if (col >= MAXCOLS) {
  500.         skiptoeol(ifp);
  501.         return (col);
  502.     }
  503.     do {
  504.         if (faxin.rawzeros >= 11) {
  505.         nextbit = rawgetbit(ifp);
  506.         if (nextbit) {
  507.             if (col == 0) {
  508.             /* XXX should be 6 */
  509.             faxin.endoffile = (++faxin.eols == 3);
  510.             if (verbose) {
  511.                 fprintf(stderr, "empty row %d: found %d so far, eof=%d\n",
  512.                 faxin.row, faxin.eols, faxin.endoffile);
  513.             }
  514.             }
  515. #ifndef notdef
  516.             if (col && col < LINE_BITS)
  517.             fprintf(stderr, "warning, row %d short (len %d)\n",
  518.                    faxin.row, col);
  519. #endif                /* notdef */
  520.             return col;
  521.         }
  522.         if (feof(ifp)) {
  523.             faxin.endoffile = 1;
  524.             return col;
  525.         }
  526.         } else
  527.         nextbit = rawgetbit(ifp);
  528.         curcode = (curcode << 1) + nextbit;
  529.         curlen++;
  530.     } while (curcode <= 0);
  531.     if (col != 0)
  532.         faxin.eols = 0;
  533.     if (curlen > 13) {
  534.         fprintf(stderr, "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL\n",
  535.                faxin.row, col, curlen, curcode);
  536.         skiptoeol(ifp);
  537.         return (col);
  538.     }
  539.     if (color) {
  540.         if (curlen < 4)
  541.         continue;
  542.         te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  543.     } else {
  544.         if (curlen < 2)
  545.         continue;
  546.         te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  547.     }
  548.     if (!te)
  549.         continue;
  550.     switch (te->tabid) {
  551.     case TWTABLE:
  552.     case TBTABLE:
  553.         count += te->count;
  554.         if (col + count > MAXCOLS)
  555.         count = MAXCOLS - col;
  556.         if (count > 0) {
  557.         if (color) {
  558.             putwhitebits(count);
  559.         } else {
  560.             putblackbits(count);
  561.         }
  562.         col += count;
  563.         count = 0;
  564.         }
  565.         curcode = 0;
  566.         curlen = 0;
  567.         color = !color;
  568.         break;
  569.     case MWTABLE:
  570.     case MBTABLE:
  571.         count += te->count;
  572.         curcode = 0;
  573.         curlen = 0;
  574.         break;
  575.     case EXTABLE:
  576.         count += te->count;
  577.         curcode = 0;
  578.         curlen = 0;
  579.         break;
  580.     default:
  581.         fprintf(stderr, "internal bad poop\n");
  582.     }
  583.     }
  584.     return -1;        /* End of page */
  585. }
  586.  
  587. static void
  588. skiptoeol(ifp)
  589. FILE           *ifp;
  590. {
  591.     while (faxin.rawzeros < 11)
  592.     (void) rawgetbit(ifp);
  593.     for (;;) {
  594.     if (feof(ifp) || rawgetbit(ifp))
  595.         break;
  596.     }
  597. }
  598.  
  599.  
  600. static int
  601. rawgetbit(ifp)
  602. FILE           *ifp;
  603. {
  604.     int         b;
  605.  
  606.     if ((faxin.shbit & 0xff) == 0) {
  607.     faxin.shdata = getc(ifp);
  608.     if (faxin.shdata == EOF) {
  609.         fprintf(stderr, "EOF / read error at line %d\n", faxin.eols);
  610.         faxin.shdata = 0;
  611.     }
  612.     faxin.shbit = faxin.reversebits ? 0x01 : 0x80;
  613.     }
  614.     if (faxin.shdata & faxin.shbit) {
  615.     faxin.rawzeros = 0;
  616.     b = 1;
  617.     } else {
  618.     faxin.rawzeros++;
  619.     b = 0;
  620.     }
  621.     if (faxin.reversebits)
  622.     faxin.shbit <<= 1;
  623.     else
  624.     faxin.shbit >>= 1;
  625.     return b;
  626. }
  627. @
  628.  
  629.  
  630. 1.4
  631. log
  632. @Improve on bit order terminology: use msb/lsb first.
  633. @
  634. text
  635. @d13 1
  636. a13 1
  637. /* $Id: fromfax.c,v 1.3 1993/08/20 03:45:27 Rhialto Exp $
  638. d15 3
  639. d170 1
  640. a170 1
  641.         printf("internal bad poop\n");
  642. d178 3
  643. a180 3
  644.     int            normerrors = 0;
  645.     int            reverrors = 0;
  646.     int            i;
  647. d209 1
  648. a209 1
  649.     if (normerrors < reverrors)
  650. d211 2
  651. a212 1
  652.     else
  653. d214 1
  654. d217 10
  655. d228 1
  656. a228 1
  657. faxin_open_fp(FILE *ifp, int dostretch, int doreverse)
  658. d257 4
  659. a260 4
  660.         faxin.reversebits = doreverse;
  661.         if (doreverse < 0) 
  662.         doreverse = infer_bitorder(ifp);
  663.         if (doreverse < 0) {
  664. d365 1
  665. a365 1
  666.         printf("internal error: addtohash fatal hash collision\n");
  667. d385 1
  668. a385 1
  669.     printf(
  670. d463 1
  671. a463 1
  672.             if (col == 0)
  673. d466 5
  674. a470 2
  675.             else
  676.             faxin.eols = 0;
  677. d473 1
  678. a473 1
  679.             printf("warning, row %d short (len %d)\n",
  680. d476 1
  681. a476 1
  682.             return (col);
  683. d487 2
  684. d490 1
  685. a490 1
  686.         printf("bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL\n",
  687. d537 1
  688. a537 1
  689.         printf("internal bad poop\n");
  690. d565 1
  691. a565 1
  692.         printf("EOF / read error at line %d\n", faxin.eols);
  693. @
  694.  
  695.  
  696. 1.3
  697. log
  698. @Add hack for auto-detecting fax bit order.
  699. @
  700. text
  701. @d13 1
  702. a13 1
  703. /* $Id: fromfax.c,v 1.3 1993/08/20 02:48:24 Rhialto Exp $
  704. d15 3
  705. d183 1
  706. a183 1
  707.     printf("try normal bit order...");
  708. d195 1
  709. a195 1
  710.     printf("try reverse bit order...");
  711. @
  712.  
  713.  
  714. 1.2
  715. log
  716. @First real RCS checkin
  717. @
  718. text
  719. @d13 8
  720. a20 2
  721. /* $Id$
  722.  * $Log$
  723. d29 6
  724. d43 1
  725. d74 1
  726. d88 124
  727. d213 1
  728. a213 1
  729. faxin_open_fp(FILE *ifp, int dostretch)
  730. d234 3
  731. d238 12
  732. d275 1
  733. a275 1
  734.         if (feof(ifp))
  735. d277 1
  736. d313 2
  737. d316 1
  738. a316 1
  739.     if (faxin.raw && feof(ifp))
  740. d318 1
  741. d329 1
  742. a329 1
  743.     if (feof(ifp))
  744. d331 1
  745. d437 1
  746. d456 1
  747. a456 1
  748.                    -1, col);
  749. d471 1
  750. a471 1
  751.                -1, col, curlen, curcode);
  752. @
  753.  
  754.  
  755. 1.1
  756. log
  757. @Initial revision
  758. @
  759. text
  760. @d13 3
  761. @
  762.