home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / tiff / tif_fax3.h < prev    next >
C/C++ Source or Header  |  1999-11-30  |  16KB  |  523 lines

  1. /* $Id: tif_fax3.h,v 1.1 1999/11/30 18:42:31 RR Exp $ */
  2.  
  3. /*
  4.  * Copyright (c) 1990-1997 Sam Leffler
  5.  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26.  
  27. #ifndef _FAX3_
  28. #define    _FAX3_
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
  33.  *
  34.  * Decoder support is derived, with permission, from the code
  35.  * in Frank Cringle's viewfax program;
  36.  *      Copyright (C) 1990, 1995  Frank D. Cringle.
  37.  */
  38. #include "tiff.h"
  39.  
  40. /*
  41.  * To override the default routine used to image decoded
  42.  * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
  43.  * The routine must have the type signature given below;
  44.  * for example:
  45.  *
  46.  * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
  47.  *
  48.  * where buf is place to set the bits, runs is the array of b&w run
  49.  * lengths (white then black), erun is the last run in the array, and
  50.  * lastx is the width of the row in pixels.  Fill routines can assume
  51.  * the run array has room for at least lastx runs and can overwrite
  52.  * data in the run array as needed (e.g. to append zero runs to bring
  53.  * the count up to a nice multiple).
  54.  */
  55. typedef    void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
  56.  
  57. /*
  58.  * The default run filler; made external for other decoders.
  59.  */
  60. #if defined(__cplusplus)
  61. extern "C" {
  62. #endif
  63. extern    void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
  64. #if defined(__cplusplus)
  65. }
  66. #endif
  67.  
  68.  
  69. /* finite state machine codes */
  70. #define S_Null        0
  71. #define S_Pass        1
  72. #define S_Horiz        2
  73. #define S_V0        3
  74. #define S_VR        4
  75. #define S_VL        5
  76. #define S_Ext        6
  77. #define S_TermW        7
  78. #define S_TermB        8
  79. #define S_MakeUpW    9
  80. #define S_MakeUpB    10
  81. #define S_MakeUp    11
  82. #define S_EOL        12
  83.  
  84. typedef struct {        /* state table entry */
  85.     unsigned char State;    /* see above */
  86.     unsigned char Width;    /* width of code in bits */
  87.     uint32    Param;        /* unsigned 32-bit run length in bits */
  88. } TIFFFaxTabEnt;
  89.  
  90. extern    const TIFFFaxTabEnt TIFFFaxMainTable[];
  91. extern    const TIFFFaxTabEnt TIFFFaxWhiteTable[];
  92. extern    const TIFFFaxTabEnt TIFFFaxBlackTable[];
  93.  
  94. /*
  95.  * The following macros define the majority of the G3/G4 decoder
  96.  * algorithm using the state tables defined elsewhere.  To build
  97.  * a decoder you need some setup code and some glue code. Note
  98.  * that you may also need/want to change the way the NeedBits*
  99.  * macros get input data if, for example, you know the data to be
  100.  * decoded is properly aligned and oriented (doing so before running
  101.  * the decoder can be a big performance win).
  102.  *
  103.  * Consult the decoder in the TIFF library for an idea of what you
  104.  * need to define and setup to make use of these definitions.
  105.  *
  106.  * NB: to enable a debugging version of these macros define FAX3_DEBUG
  107.  *     before including this file.  Trace output goes to stdout.
  108.  */
  109.  
  110. #ifndef EndOfData
  111. #define EndOfData()    (cp >= ep)
  112. #endif
  113. /*
  114.  * Need <=8 or <=16 bits of input data.  Unlike viewfax we
  115.  * cannot use/assume a word-aligned, properly bit swizzled
  116.  * input data set because data may come from an arbitrarily
  117.  * aligned, read-only source such as a memory-mapped file.
  118.  * Note also that the viewfax decoder does not check for
  119.  * running off the end of the input data buffer.  This is
  120.  * possible for G3-encoded data because it prescans the input
  121.  * data to count EOL markers, but can cause problems for G4
  122.  * data.  In any event, we don't prescan and must watch for
  123.  * running out of data since we can't permit the library to
  124.  * scan past the end of the input data buffer.
  125.  *
  126.  * Finally, note that we must handle remaindered data at the end
  127.  * of a strip specially.  The coder asks for a fixed number of
  128.  * bits when scanning for the next code.  This may be more bits
  129.  * than are actually present in the data stream.  If we appear
  130.  * to run out of data but still have some number of valid bits
  131.  * remaining then we makeup the requested amount with zeros and
  132.  * return successfully.  If the returned data is incorrect then
  133.  * we should be called again and get a premature EOF error;
  134.  * otherwise we should get the right answer.
  135.  */
  136. #ifndef NeedBits8
  137. #define NeedBits8(n,eoflab) do {                    \
  138.     if (BitsAvail < (n)) {                        \
  139.     if (EndOfData()) {                        \
  140.         if (BitsAvail == 0)            /* no valid bits */    \
  141.         goto eoflab;                        \
  142.         BitsAvail = (n);            /* pad with zeros */    \
  143.     } else {                            \
  144.         BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;        \
  145.         BitsAvail += 8;                        \
  146.     }                                \
  147.     }                                    \
  148. } while (0)
  149. #endif
  150. #ifndef NeedBits16
  151. #define NeedBits16(n,eoflab) do {                    \
  152.     if (BitsAvail < (n)) {                        \
  153.     if (EndOfData()) {                        \
  154.         if (BitsAvail == 0)            /* no valid bits */    \
  155.         goto eoflab;                        \
  156.         BitsAvail = (n);            /* pad with zeros */    \
  157.     } else {                            \
  158.         BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;        \
  159.         if ((BitsAvail += 8) < (n)) {                \
  160.         if (EndOfData()) {                    \
  161.             /* NB: we know BitsAvail is non-zero here */    \
  162.             BitsAvail = (n);        /* pad with zeros */    \
  163.         } else {                        \
  164.             BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;    \
  165.             BitsAvail += 8;                    \
  166.         }                            \
  167.         }                                \
  168.     }                                \
  169.     }                                    \
  170. } while (0)
  171. #endif
  172. #define GetBits(n)    (BitAcc & ((1<<(n))-1))
  173. #define ClrBits(n) do {                            \
  174.     BitsAvail -= (n);                            \
  175.     BitAcc >>= (n);                            \
  176. } while (0)
  177.  
  178. #ifdef FAX3_DEBUG
  179. static const char* StateNames[] = {
  180.     "Null   ",
  181.     "Pass   ",
  182.     "Horiz  ",
  183.     "V0     ",
  184.     "VR     ",
  185.     "VL     ",
  186.     "Ext    ",
  187.     "TermW  ",
  188.     "TermB  ",
  189.     "MakeUpW",
  190.     "MakeUpB",
  191.     "MakeUp ",
  192.     "EOL    ",
  193. };
  194. #define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
  195. #define LOOKUP8(wid,tab,eoflab) do {                    \
  196.     int t;                                \
  197.     NeedBits8(wid,eoflab);                        \
  198.     TabEnt = tab + GetBits(wid);                    \
  199.     printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,        \
  200.        StateNames[TabEnt->State], TabEnt->Param);            \
  201.     for (t = 0; t < TabEnt->Width; t++)                    \
  202.     DEBUG_SHOW;                            \
  203.     putchar('\n');                            \
  204.     fflush(stdout);                            \
  205.     ClrBits(TabEnt->Width);                        \
  206. } while (0)
  207. #define LOOKUP16(wid,tab,eoflab) do {                    \
  208.     int t;                                \
  209.     NeedBits16(wid,eoflab);                        \
  210.     TabEnt = tab + GetBits(wid);                    \
  211.     printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,        \
  212.        StateNames[TabEnt->State], TabEnt->Param);            \
  213.     for (t = 0; t < TabEnt->Width; t++)                    \
  214.     DEBUG_SHOW;                            \
  215.     putchar('\n');                            \
  216.     fflush(stdout);                            \
  217.     ClrBits(TabEnt->Width);                        \
  218. } while (0)
  219.  
  220. #define SETVAL(x) do {                            \
  221.     *pa++ = RunLength + (x);                        \
  222.     printf("SETVAL: %d\t%d\n", RunLength + (x), a0);            \
  223.     a0 += x;                                \
  224.     RunLength = 0;                            \
  225. } while (0)
  226. #else
  227. #define LOOKUP8(wid,tab,eoflab) do {                    \
  228.     NeedBits8(wid,eoflab);                        \
  229.     TabEnt = tab + GetBits(wid);                    \
  230.     ClrBits(TabEnt->Width);                        \
  231. } while (0)
  232. #define LOOKUP16(wid,tab,eoflab) do {                    \
  233.     NeedBits16(wid,eoflab);                        \
  234.     TabEnt = tab + GetBits(wid);                    \
  235.     ClrBits(TabEnt->Width);                        \
  236. } while (0)
  237.  
  238. /*
  239.  * Append a run to the run length array for the
  240.  * current row and reset decoding state.
  241.  */
  242. #define SETVAL(x) do {                            \
  243.     *pa++ = RunLength + (x);                        \
  244.     a0 += (x);                                \
  245.     RunLength = 0;                            \
  246. } while (0)
  247. #endif
  248.  
  249. /*
  250.  * Synchronize input decoding at the start of each
  251.  * row by scanning for an EOL (if appropriate) and
  252.  * skipping any trash data that might be present
  253.  * after a decoding error.  Note that the decoding
  254.  * done elsewhere that recognizes an EOL only consumes
  255.  * 11 consecutive zero bits.  This means that if EOLcnt
  256.  * is non-zero then we still need to scan for the final flag
  257.  * bit that is part of the EOL code.
  258.  */
  259. #define    SYNC_EOL(eoflab) do {                        \
  260.     if (EOLcnt == 0) {                            \
  261.     for (;;) {                            \
  262.         NeedBits16(11,eoflab);                    \
  263.         if (GetBits(11) == 0)                    \
  264.         break;                            \
  265.         ClrBits(1);                            \
  266.     }                                \
  267.     }                                    \
  268.     for (;;) {                                \
  269.     NeedBits8(8,eoflab);                        \
  270.     if (GetBits(8))                            \
  271.         break;                            \
  272.     ClrBits(8);                            \
  273.     }                                    \
  274.     while (GetBits(1) == 0)                        \
  275.     ClrBits(1);                            \
  276.     ClrBits(1);                /* EOL bit */            \
  277.     EOLcnt = 0;                /* reset EOL counter/flag */    \
  278. } while (0)
  279.  
  280. /*
  281.  * Cleanup the array of runs after decoding a row.
  282.  * We adjust final runs to insure the user buffer is not
  283.  * overwritten and/or undecoded area is white filled.
  284.  */
  285. #define    CLEANUP_RUNS() do {                        \
  286.     if (RunLength)                            \
  287.     SETVAL(0);                            \
  288.     if (a0 != lastx) {                            \
  289.     badlength(a0, lastx);                        \
  290.     while (a0 > lastx && pa > thisrun)                \
  291.         a0 -= *--pa;                        \
  292.     if (a0 < lastx) {                        \
  293.         if (a0 < 0)                            \
  294.         a0 = 0;                            \
  295.         if ((pa-thisrun)&1)                        \
  296.         SETVAL(0);                        \
  297.         SETVAL(lastx - a0);                        \
  298.     } else if (a0 > lastx) {                    \
  299.         SETVAL(lastx);                        \
  300.         SETVAL(0);                            \
  301.     }                                \
  302.     }                                    \
  303. } while (0)
  304.  
  305. /*
  306.  * Decode a line of 1D-encoded data.
  307.  *
  308.  * The line expanders are written as macros so that they can be reused
  309.  * but still have direct access to the local variables of the "calling"
  310.  * function.
  311.  *
  312.  * Note that unlike the original version we have to explicitly test for
  313.  * a0 >= lastx after each black/white run is decoded.  This is because
  314.  * the original code depended on the input data being zero-padded to
  315.  * insure the decoder recognized an EOL before running out of data.
  316.  */
  317. #define EXPAND1D(eoflab) do {                        \
  318.     for (;;) {                                \
  319.     for (;;) {                            \
  320.         LOOKUP16(12, TIFFFaxWhiteTable, eof1d);            \
  321.         switch (TabEnt->State) {                    \
  322.         case S_EOL:                            \
  323.         EOLcnt = 1;                        \
  324.         goto done1d;                        \
  325.         case S_TermW:                        \
  326.         SETVAL(TabEnt->Param);                    \
  327.         goto doneWhite1d;                    \
  328.         case S_MakeUpW:                        \
  329.         case S_MakeUp:                        \
  330.         a0 += TabEnt->Param;                    \
  331.         RunLength += TabEnt->Param;                \
  332.         break;                            \
  333.         default:                            \
  334.         unexpected("WhiteTable", a0);                \
  335.         goto done1d;                        \
  336.         }                                \
  337.     }                                \
  338.     doneWhite1d:                            \
  339.     if (a0 >= lastx)                        \
  340.         goto done1d;                        \
  341.     for (;;) {                            \
  342.         LOOKUP16(13, TIFFFaxBlackTable, eof1d);            \
  343.         switch (TabEnt->State) {                    \
  344.         case S_EOL:                            \
  345.         EOLcnt = 1;                        \
  346.         goto done1d;                        \
  347.         case S_TermB:                        \
  348.         SETVAL(TabEnt->Param);                    \
  349.         goto doneBlack1d;                    \
  350.         case S_MakeUpB:                        \
  351.         case S_MakeUp:                        \
  352.         a0 += TabEnt->Param;                    \
  353.         RunLength += TabEnt->Param;                \
  354.         break;                            \
  355.         default:                            \
  356.         unexpected("BlackTable", a0);                \
  357.         goto done1d;                        \
  358.         }                                \
  359.     }                                \
  360.     doneBlack1d:                            \
  361.     if (a0 >= lastx)                        \
  362.         goto done1d;                        \
  363.     }                                    \
  364. eof1d:                                    \
  365.     prematureEOF(a0);                            \
  366.     CLEANUP_RUNS();                            \
  367.     goto eoflab;                            \
  368. done1d:                                    \
  369.     CLEANUP_RUNS();                            \
  370. } while (0)
  371.  
  372. /*
  373.  * Update the value of b1 using the array
  374.  * of runs for the reference line.
  375.  */
  376. #define CHECK_b1 do {                            \
  377.     if (pa != thisrun) while (b1 <= a0 && b1 < lastx) {            \
  378.     b1 += pb[0] + pb[1];                        \
  379.     pb += 2;                            \
  380.     }                                    \
  381. } while (0)
  382.  
  383. /*
  384.  * Expand a row of 2D-encoded data.
  385.  */
  386. #define EXPAND2D(eoflab) do {                        \
  387.     while (a0 < lastx) {                        \
  388.     LOOKUP8(7, TIFFFaxMainTable, eof2d);                \
  389.     switch (TabEnt->State) {                    \
  390.     case S_Pass:                            \
  391.         CHECK_b1;                            \
  392.         b1 += *pb++;                        \
  393.         RunLength += b1 - a0;                    \
  394.         a0 = b1;                            \
  395.         b1 += *pb++;                        \
  396.         break;                            \
  397.     case S_Horiz:                            \
  398.         if ((pa-thisrun)&1) {                    \
  399.         for (;;) {    /* black first */            \
  400.             LOOKUP16(13, TIFFFaxBlackTable, eof2d);        \
  401.             switch (TabEnt->State) {                \
  402.             case S_TermB:                    \
  403.             SETVAL(TabEnt->Param);                \
  404.             goto doneWhite2da;                \
  405.             case S_MakeUpB:                    \
  406.             case S_MakeUp:                    \
  407.             a0 += TabEnt->Param;                \
  408.             RunLength += TabEnt->Param;            \
  409.             break;                        \
  410.             default:                        \
  411.             goto badBlack2d;                \
  412.             }                            \
  413.         }                            \
  414.         doneWhite2da:;                        \
  415.         for (;;) {    /* then white */            \
  416.             LOOKUP16(12, TIFFFaxWhiteTable, eof2d);        \
  417.             switch (TabEnt->State) {                \
  418.             case S_TermW:                    \
  419.             SETVAL(TabEnt->Param);                \
  420.             goto doneBlack2da;                \
  421.             case S_MakeUpW:                    \
  422.             case S_MakeUp:                    \
  423.             a0 += TabEnt->Param;                \
  424.             RunLength += TabEnt->Param;            \
  425.             break;                        \
  426.             default:                        \
  427.             goto badWhite2d;                \
  428.             }                            \
  429.         }                            \
  430.         doneBlack2da:;                        \
  431.         } else {                            \
  432.         for (;;) {    /* white first */            \
  433.             LOOKUP16(12, TIFFFaxWhiteTable, eof2d);        \
  434.             switch (TabEnt->State) {                \
  435.             case S_TermW:                    \
  436.             SETVAL(TabEnt->Param);                \
  437.             goto doneWhite2db;                \
  438.             case S_MakeUpW:                    \
  439.             case S_MakeUp:                    \
  440.             a0 += TabEnt->Param;                \
  441.             RunLength += TabEnt->Param;            \
  442.             break;                        \
  443.             default:                        \
  444.             goto badWhite2d;                \
  445.             }                            \
  446.         }                            \
  447.         doneWhite2db:;                        \
  448.         for (;;) {    /* then black */            \
  449.             LOOKUP16(13, TIFFFaxBlackTable, eof2d);        \
  450.             switch (TabEnt->State) {                \
  451.             case S_TermB:                    \
  452.             SETVAL(TabEnt->Param);                \
  453.             goto doneBlack2db;                \
  454.             case S_MakeUpB:                    \
  455.             case S_MakeUp:                    \
  456.             a0 += TabEnt->Param;                \
  457.             RunLength += TabEnt->Param;            \
  458.             break;                        \
  459.             default:                        \
  460.             goto badBlack2d;                \
  461.             }                            \
  462.         }                            \
  463.         doneBlack2db:;                        \
  464.         }                                \
  465.         CHECK_b1;                            \
  466.         break;                            \
  467.     case S_V0:                            \
  468.         CHECK_b1;                            \
  469.         SETVAL(b1 - a0);                        \
  470.         b1 += *pb++;                        \
  471.         break;                            \
  472.     case S_VR:                            \
  473.         CHECK_b1;                            \
  474.         SETVAL(b1 - a0 + TabEnt->Param);                \
  475.         b1 += *pb++;                        \
  476.         break;                            \
  477.     case S_VL:                            \
  478.         CHECK_b1;                            \
  479.         SETVAL(b1 - a0 - TabEnt->Param);                \
  480.         b1 -= *--pb;                        \
  481.         break;                            \
  482.     case S_Ext:                            \
  483.         *pa++ = lastx - a0;                        \
  484.         extension(a0);                        \
  485.         goto eol2d;                            \
  486.     case S_EOL:                            \
  487.         *pa++ = lastx - a0;                        \
  488.         NeedBits8(5,eof2d);                        \
  489.         if (GetBits(5))                        \
  490.         unexpected("EOL", a0);                    \
  491.         EOLcnt = 1;                            \
  492.         goto eol2d;                            \
  493.     default:                            \
  494.     badMain2d:                            \
  495.         unexpected("MainTable", a0);                \
  496.         goto eol2d;                            \
  497.     badBlack2d:                            \
  498.         unexpected("BlackTable", a0);                \
  499.         goto eol2d;                            \
  500.     badWhite2d:                            \
  501.         unexpected("WhiteTable", a0);                \
  502.         goto eol2d;                            \
  503.     eof2d:                                \
  504.         prematureEOF(a0);                        \
  505.         CLEANUP_RUNS();                        \
  506.         goto eoflab;                        \
  507.     }                                \
  508.     }                                    \
  509.     if (RunLength) {                            \
  510.     if (RunLength + a0 < lastx) {                    \
  511.         /* expect a final V0 */                    \
  512.         NeedBits8(1,eof2d);                        \
  513.         if (!GetBits(1))                        \
  514.         goto badMain2d;                        \
  515.         ClrBits(1);                            \
  516.     }                                \
  517.     SETVAL(0);                            \
  518.     }                                    \
  519. eol2d:                                    \
  520.     CLEANUP_RUNS();                            \
  521. } while (0)
  522. #endif /* _FAX3_ */
  523.