tif_fax3.h
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:16k
- /* $Id: tif_fax3.h,v 1.4 2006/04/18 19:15:55 faxguy Exp $ */
- /*
- * Copyright (c) 1990-1997 Sam Leffler
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
- #ifndef _FAX3_
- #define _FAX3_
- /*
- * TIFF Library.
- *
- * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
- *
- * Decoder support is derived, with permission, from the code
- * in Frank Cringle's viewfax program;
- * Copyright (C) 1990, 1995 Frank D. Cringle.
- */
- #include "tiff.h"
- /*
- * To override the default routine used to image decoded
- * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
- * The routine must have the type signature given below;
- * for example:
- *
- * fillruns(unsigned char* buf, tiff_runlen_t* runs, tiff_runlen_t* erun, tiff_runlen_t lastx)
- *
- * where buf is place to set the bits, runs is the array of b&w run
- * lengths (white then black), erun is the last run in the array, and
- * lastx is the width of the row in pixels. Fill routines can assume
- * the run array has room for at least lastx runs and can overwrite
- * data in the run array as needed (e.g. to append zero runs to bring
- * the count up to a nice multiple).
- */
- typedef void (*TIFFFaxFillFunc)(unsigned char*, tiff_runlen_t*, tiff_runlen_t*, tiff_runlen_t);
- /*
- * The default run filler; made external for other decoders.
- */
- #if defined(__cplusplus)
- extern "C" {
- #endif
- extern void _TIFFFax3fillruns(unsigned char*, tiff_runlen_t*, tiff_runlen_t*, tiff_runlen_t);
- #if defined(__cplusplus)
- }
- #endif
- /* finite state machine codes */
- #define S_Null 0
- #define S_Pass 1
- #define S_Horiz 2
- #define S_V0 3
- #define S_VR 4
- #define S_VL 5
- #define S_Ext 6
- #define S_TermW 7
- #define S_TermB 8
- #define S_MakeUpW 9
- #define S_MakeUpB 10
- #define S_MakeUp 11
- #define S_EOL 12
- typedef struct { /* state table entry */
- unsigned char State; /* see above */
- unsigned char Width; /* width of code in bits */
- tiff_runlen_t Param; /* unsigned 32-bit run length in bits */
- } TIFFFaxTabEnt;
- extern const TIFFFaxTabEnt TIFFFaxMainTable[];
- extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
- extern const TIFFFaxTabEnt TIFFFaxBlackTable[];
- /*
- * The following macros define the majority of the G3/G4 decoder
- * algorithm using the state tables defined elsewhere. To build
- * a decoder you need some setup code and some glue code. Note
- * that you may also need/want to change the way the NeedBits*
- * macros get input data if, for example, you know the data to be
- * decoded is properly aligned and oriented (doing so before running
- * the decoder can be a big performance win).
- *
- * Consult the decoder in the TIFF library for an idea of what you
- * need to define and setup to make use of these definitions.
- *
- * NB: to enable a debugging version of these macros define FAX3_DEBUG
- * before including this file. Trace output goes to stdout.
- */
- #ifndef EndOfData
- #define EndOfData() (cp >= ep)
- #endif
- /*
- * Need <=8 or <=16 bits of input data. Unlike viewfax we
- * cannot use/assume a word-aligned, properly bit swizzled
- * input data set because data may come from an arbitrarily
- * aligned, read-only source such as a memory-mapped file.
- * Note also that the viewfax decoder does not check for
- * running off the end of the input data buffer. This is
- * possible for G3-encoded data because it prescans the input
- * data to count EOL markers, but can cause problems for G4
- * data. In any event, we don't prescan and must watch for
- * running out of data since we can't permit the library to
- * scan past the end of the input data buffer.
- *
- * Finally, note that we must handle remaindered data at the end
- * of a strip specially. The coder asks for a fixed number of
- * bits when scanning for the next code. This may be more bits
- * than are actually present in the data stream. If we appear
- * to run out of data but still have some number of valid bits
- * remaining then we makeup the requested amount with zeros and
- * return successfully. If the returned data is incorrect then
- * we should be called again and get a premature EOF error;
- * otherwise we should get the right answer.
- */
- #ifndef NeedBits8
- #define NeedBits8(n,eoflab) do {
- if (BitsAvail < (n)) {
- if (EndOfData()) {
- if (BitsAvail == 0) /* no valid bits */
- goto eoflab;
- BitsAvail = (n); /* pad with zeros */
- } else {
- BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;
- BitsAvail += 8;
- }
- }
- } while (0)
- #endif
- #ifndef NeedBits16
- #define NeedBits16(n,eoflab) do {
- if (BitsAvail < (n)) {
- if (EndOfData()) {
- if (BitsAvail == 0) /* no valid bits */
- goto eoflab;
- BitsAvail = (n); /* pad with zeros */
- } else {
- BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;
- if ((BitsAvail += 8) < (n)) {
- if (EndOfData()) {
- /* NB: we know BitsAvail is non-zero here */
- BitsAvail = (n); /* pad with zeros */
- } else {
- BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;
- BitsAvail += 8;
- }
- }
- }
- }
- } while (0)
- #endif
- #define GetBits(n) (BitAcc & ((1<<(n))-1))
- #define ClrBits(n) do {
- BitsAvail -= (n);
- BitAcc >>= (n);
- } while (0)
- #ifdef FAX3_DEBUG
- static const char* StateNames[] = {
- "Null ",
- "Pass ",
- "Horiz ",
- "V0 ",
- "VR ",
- "VL ",
- "Ext ",
- "TermW ",
- "TermB ",
- "MakeUpW",
- "MakeUpB",
- "MakeUp ",
- "EOL ",
- };
- #define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
- #define LOOKUP8(wid,tab,eoflab) do {
- int t;
- NeedBits8(wid,eoflab);
- TabEnt = tab + GetBits(wid);
- printf("%08lX/%d: %s%5dt", (long) BitAcc, BitsAvail,
- StateNames[TabEnt->State], TabEnt->Param);
- for (t = 0; t < TabEnt->Width; t++)
- DEBUG_SHOW;
- putchar('n');
- fflush(stdout);
- ClrBits(TabEnt->Width);
- } while (0)
- #define LOOKUP16(wid,tab,eoflab) do {
- int t;
- NeedBits16(wid,eoflab);
- TabEnt = tab + GetBits(wid);
- printf("%08lX/%d: %s%5dt", (long) BitAcc, BitsAvail,
- StateNames[TabEnt->State], TabEnt->Param);
- for (t = 0; t < TabEnt->Width; t++)
- DEBUG_SHOW;
- putchar('n');
- fflush(stdout);
- ClrBits(TabEnt->Width);
- } while (0)
- #define SETVAL(x) do {
- *pa++ = RunLength + (x);
- printf("SETVAL: %dt%dn", RunLength + (x), a0);
- a0 += x;
- RunLength = 0;
- } while (0)
- #else
- #define LOOKUP8(wid,tab,eoflab) do {
- NeedBits8(wid,eoflab);
- TabEnt = tab + GetBits(wid);
- ClrBits(TabEnt->Width);
- } while (0)
- #define LOOKUP16(wid,tab,eoflab) do {
- NeedBits16(wid,eoflab);
- TabEnt = tab + GetBits(wid);
- ClrBits(TabEnt->Width);
- } while (0)
- /*
- * Append a run to the run length array for the
- * current row and reset decoding state.
- */
- #define SETVAL(x) do {
- *pa++ = RunLength + (x);
- a0 += (x);
- RunLength = 0;
- } while (0)
- #endif
- /*
- * Synchronize input decoding at the start of each
- * row by scanning for an EOL (if appropriate) and
- * skipping any trash data that might be present
- * after a decoding error. Note that the decoding
- * done elsewhere that recognizes an EOL only consumes
- * 11 consecutive zero bits. This means that if EOLcnt
- * is non-zero then we still need to scan for the final flag
- * bit that is part of the EOL code.
- *
- * In order to prevent getting forever stuck in these loops
- * (perhaps by a hung modem or hung sender) we raiseRTC if
- * it appears to be the case.
- */
- #define SYNC_EOL(eoflab) do {
- if (EOLcnt == 0) {
- for (u_long i = 0;; i++) {
- NeedBits16(11,eoflab);
- if (GetBits(11) == 0)
- break;
- ClrBits(1);
- if (i > 150000) raiseRTC();
- }
- }
- for (u_long i = 0;; i++) {
- NeedBits8(8,eoflab);
- if (GetBits(8))
- break;
- ClrBits(8);
- if (i > 150000) raiseRTC();
- }
- while (GetBits(1) == 0)
- ClrBits(1);
- ClrBits(1); /* EOL bit */
- EOLcnt = 0; /* reset EOL counter/flag */
- } while (0)
- /*
- * Cleanup the array of runs after decoding a row.
- * We adjust final runs to insure the user buffer is not
- * overwritten and/or undecoded area is white filled.
- */
- #define CLEANUP_RUNS() do {
- if (RunLength)
- SETVAL(0);
- if ((tiff_runlen_t)a0 != lastx) {
- badlength((tiff_runlen_t)a0, lastx);
- while ((tiff_runlen_t)a0 > lastx && pa > thisrun)
- a0 -= *--pa;
- if ((tiff_runlen_t)a0 < lastx) {
- if (a0 < 0)
- a0 = 0;
- if ((pa-thisrun)&1)
- SETVAL(0);
- SETVAL(lastx - a0);
- } else if ((tiff_runlen_t)a0 > lastx) {
- SETVAL(lastx);
- SETVAL(0);
- }
- }
- } while (0)
- /*
- * Decode a line of 1D-encoded data.
- *
- * The line expanders are written as macros so that they can be reused
- * but still have direct access to the local variables of the "calling"
- * function.
- *
- * Note that unlike the original version we have to explicitly test for
- * a0 >= lastx after each black/white run is decoded. This is because
- * the original code depended on the input data being zero-padded to
- * insure the decoder recognized an EOL before running out of data.
- */
- #define EXPAND1D(eoflab) do {
- for (;;) {
- for (;;) {
- LOOKUP16(12, TIFFFaxWhiteTable, eof1d);
- switch (TabEnt->State) {
- case S_EOL:
- EOLcnt = 1;
- goto done1d;
- case S_TermW:
- SETVAL(TabEnt->Param);
- goto doneWhite1d;
- case S_MakeUpW:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- unexpected("WhiteTable", a0);
- goto done1d;
- }
- }
- doneWhite1d:
- if ((tiff_runlen_t)a0 >= lastx)
- goto done1d;
- for (;;) {
- LOOKUP16(13, TIFFFaxBlackTable, eof1d);
- switch (TabEnt->State) {
- case S_EOL:
- EOLcnt = 1;
- goto done1d;
- case S_TermB:
- SETVAL(TabEnt->Param);
- goto doneBlack1d;
- case S_MakeUpB:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- unexpected("BlackTable", a0);
- goto done1d;
- }
- }
- doneBlack1d:
- if ((tiff_runlen_t)a0 >= lastx)
- goto done1d;
- if( *(pa-1) == 0 && *(pa-2) == 0 )
- pa -= 2;
- }
- eof1d:
- prematureEOF(a0);
- CLEANUP_RUNS();
- goto eoflab;
- done1d:
- CLEANUP_RUNS();
- } while (0)
- /*
- * Update the value of b1 using the array
- * of runs for the reference line.
- */
- #define CHECK_b1 do {
- if (pa != thisrun) while (b1 <= a0 && (tiff_runlen_t)b1 < lastx) {
- b1 += pb[0] + pb[1];
- pb += 2;
- }
- } while (0)
- /*
- * Expand a row of 2D-encoded data.
- */
- #define EXPAND2D(eoflab) do {
- while ((tiff_runlen_t)a0 < lastx) {
- LOOKUP8(7, TIFFFaxMainTable, eof2d);
- switch (TabEnt->State) {
- case S_Pass:
- CHECK_b1;
- b1 += *pb++;
- RunLength += b1 - a0;
- a0 = b1;
- b1 += *pb++;
- break;
- case S_Horiz:
- if ((pa-thisrun)&1) {
- for (;;) { /* black first */
- LOOKUP16(13, TIFFFaxBlackTable, eof2d);
- switch (TabEnt->State) {
- case S_TermB:
- SETVAL(TabEnt->Param);
- goto doneWhite2da;
- case S_MakeUpB:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- goto badBlack2d;
- }
- }
- doneWhite2da:;
- for (;;) { /* then white */
- LOOKUP16(12, TIFFFaxWhiteTable, eof2d);
- switch (TabEnt->State) {
- case S_TermW:
- SETVAL(TabEnt->Param);
- goto doneBlack2da;
- case S_MakeUpW:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- goto badWhite2d;
- }
- }
- doneBlack2da:;
- } else {
- for (;;) { /* white first */
- LOOKUP16(12, TIFFFaxWhiteTable, eof2d);
- switch (TabEnt->State) {
- case S_TermW:
- SETVAL(TabEnt->Param);
- goto doneWhite2db;
- case S_MakeUpW:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- goto badWhite2d;
- }
- }
- doneWhite2db:;
- for (;;) { /* then black */
- LOOKUP16(13, TIFFFaxBlackTable, eof2d);
- switch (TabEnt->State) {
- case S_TermB:
- SETVAL(TabEnt->Param);
- goto doneBlack2db;
- case S_MakeUpB:
- case S_MakeUp:
- a0 += TabEnt->Param;
- RunLength += TabEnt->Param;
- break;
- default:
- goto badBlack2d;
- }
- }
- doneBlack2db:;
- }
- CHECK_b1;
- break;
- case S_V0:
- CHECK_b1;
- SETVAL(b1 - a0);
- b1 += *pb++;
- break;
- case S_VR:
- CHECK_b1;
- SETVAL(b1 - a0 + TabEnt->Param);
- b1 += *pb++;
- break;
- case S_VL:
- CHECK_b1;
- SETVAL(b1 - a0 - TabEnt->Param);
- b1 -= *--pb;
- break;
- case S_Ext:
- *pa++ = lastx - a0;
- extension(a0);
- goto eol2d;
- case S_EOL:
- *pa++ = lastx - a0;
- NeedBits8(4,eof2d);
- if (GetBits(4))
- unexpected("EOL", a0);
- ClrBits(4);
- EOLcnt = 1;
- goto eol2d;
- default:
- badMain2d:
- unexpected("MainTable", a0);
- goto eol2d;
- badBlack2d:
- unexpected("BlackTable", a0);
- goto eol2d;
- badWhite2d:
- unexpected("WhiteTable", a0);
- goto eol2d;
- eof2d:
- prematureEOF(a0);
- CLEANUP_RUNS();
- goto eoflab;
- }
- }
- if (RunLength) {
- if ((tiff_runlen_t)(RunLength + a0) < lastx) {
- /* expect a final V0 */
- NeedBits8(1,eof2d);
- if (!GetBits(1))
- goto badMain2d;
- ClrBits(1);
- }
- SETVAL(0);
- }
- eol2d:
- CLEANUP_RUNS();
- } while (0)
- #endif /* _FAX3_ */