/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */12/*3* Copyright (c) 1990-1997 Sam Leffler4* Copyright (c) 1991-1997 Silicon Graphics, Inc.5*6* Permission to use, copy, modify, distribute, and sell this software and7* its documentation for any purpose is hereby granted without fee, provided8* that (i) the above copyright notices and this permission notice appear in9* all copies of the software and related documentation, and (ii) the names of10* Sam Leffler and Silicon Graphics may not be used in any advertising or11* publicity relating to the software without the specific, prior written12* permission of Sam Leffler and Silicon Graphics.13*14* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,15* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY16* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.17*18* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR19* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,20* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,21* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF22* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE23* OF THIS SOFTWARE.24*/2526#ifndef _FAX3_27#define _FAX3_28/*29* TIFF Library.30*31* CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.32*33* Decoder support is derived, with permission, from the code34* in Frank Cringle's viewfax program;35* Copyright (C) 1990, 1995 Frank D. Cringle.36*/37#include "tiff.h"3839/*40* To override the default routine used to image decoded41* spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC.42* The routine must have the type signature given below;43* for example:44*45* fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)46*47* where buf is place to set the bits, runs is the array of b&w run48* lengths (white then black), erun is the last run in the array, and49* lastx is the width of the row in pixels. Fill routines can assume50* the run array has room for at least lastx runs and can overwrite51* data in the run array as needed (e.g. to append zero runs to bring52* the count up to a nice multiple).53*/54typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);5556/*57* The default run filler; made external for other decoders.58*/59#if defined(__cplusplus)60extern "C" {61#endif62extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);63#if defined(__cplusplus)64}65#endif666768/* finite state machine codes */69#define S_Null 070#define S_Pass 171#define S_Horiz 272#define S_V0 373#define S_VR 474#define S_VL 575#define S_Ext 676#define S_TermW 777#define S_TermB 878#define S_MakeUpW 979#define S_MakeUpB 1080#define S_MakeUp 1181#define S_EOL 128283/* WARNING: do not change the layout of this structure as the HylaFAX software */84/* really depends on it. See http://bugzilla.maptools.org/show_bug.cgi?id=2636 */85typedef struct { /* state table entry */86unsigned char State; /* see above */87unsigned char Width; /* width of code in bits */88uint32 Param; /* unsigned 32-bit run length in bits (holds on 16 bit actually, but cannot be changed. See above warning) */89} TIFFFaxTabEnt;9091extern const TIFFFaxTabEnt TIFFFaxMainTable[];92extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];93extern const TIFFFaxTabEnt TIFFFaxBlackTable[];9495/*96* The following macros define the majority of the G3/G4 decoder97* algorithm using the state tables defined elsewhere. To build98* a decoder you need some setup code and some glue code. Note99* that you may also need/want to change the way the NeedBits*100* macros get input data if, for example, you know the data to be101* decoded is properly aligned and oriented (doing so before running102* the decoder can be a big performance win).103*104* Consult the decoder in the TIFF library for an idea of what you105* need to define and setup to make use of these definitions.106*107* NB: to enable a debugging version of these macros define FAX3_DEBUG108* before including this file. Trace output goes to stdout.109*/110111#ifndef EndOfData112#define EndOfData() (cp >= ep)113#endif114/*115* Need <=8 or <=16 bits of input data. Unlike viewfax we116* cannot use/assume a word-aligned, properly bit swizzled117* input data set because data may come from an arbitrarily118* aligned, read-only source such as a memory-mapped file.119* Note also that the viewfax decoder does not check for120* running off the end of the input data buffer. This is121* possible for G3-encoded data because it prescans the input122* data to count EOL markers, but can cause problems for G4123* data. In any event, we don't prescan and must watch for124* running out of data since we can't permit the library to125* scan past the end of the input data buffer.126*127* Finally, note that we must handle remaindered data at the end128* of a strip specially. The coder asks for a fixed number of129* bits when scanning for the next code. This may be more bits130* than are actually present in the data stream. If we appear131* to run out of data but still have some number of valid bits132* remaining then we makeup the requested amount with zeros and133* return successfully. If the returned data is incorrect then134* we should be called again and get a premature EOF error;135* otherwise we should get the right answer.136*/137#ifndef NeedBits8138#define NeedBits8(n,eoflab) do { \139if (BitsAvail < (n)) { \140if (EndOfData()) { \141if (BitsAvail == 0) /* no valid bits */ \142goto eoflab; \143BitsAvail = (n); /* pad with zeros */ \144} else { \145BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \146BitsAvail += 8; \147} \148} \149} while (0)150#endif151#ifndef NeedBits16152#define NeedBits16(n,eoflab) do { \153if (BitsAvail < (n)) { \154if (EndOfData()) { \155if (BitsAvail == 0) /* no valid bits */ \156goto eoflab; \157BitsAvail = (n); /* pad with zeros */ \158} else { \159BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \160if ((BitsAvail += 8) < (n)) { \161if (EndOfData()) { \162/* NB: we know BitsAvail is non-zero here */ \163BitsAvail = (n); /* pad with zeros */ \164} else { \165BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \166BitsAvail += 8; \167} \168} \169} \170} \171} while (0)172#endif173#define GetBits(n) (BitAcc & ((1<<(n))-1))174#define ClrBits(n) do { \175BitsAvail -= (n); \176BitAcc >>= (n); \177} while (0)178179#ifdef FAX3_DEBUG180static const char* StateNames[] = {181"Null ",182"Pass ",183"Horiz ",184"V0 ",185"VR ",186"VL ",187"Ext ",188"TermW ",189"TermB ",190"MakeUpW",191"MakeUpB",192"MakeUp ",193"EOL ",194};195#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')196#define LOOKUP8(wid,tab,eoflab) do { \197int t; \198NeedBits8(wid,eoflab); \199TabEnt = tab + GetBits(wid); \200printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \201StateNames[TabEnt->State], TabEnt->Param); \202for (t = 0; t < TabEnt->Width; t++) \203DEBUG_SHOW; \204putchar('\n'); \205fflush(stdout); \206ClrBits(TabEnt->Width); \207} while (0)208#define LOOKUP16(wid,tab,eoflab) do { \209int t; \210NeedBits16(wid,eoflab); \211TabEnt = tab + GetBits(wid); \212printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \213StateNames[TabEnt->State], TabEnt->Param); \214for (t = 0; t < TabEnt->Width; t++) \215DEBUG_SHOW; \216putchar('\n'); \217fflush(stdout); \218ClrBits(TabEnt->Width); \219} while (0)220221#define SETVALUE(x) do { \222*pa++ = RunLength + (x); \223printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \224a0 += x; \225RunLength = 0; \226} while (0)227#else228#define LOOKUP8(wid,tab,eoflab) do { \229NeedBits8(wid,eoflab); \230TabEnt = tab + GetBits(wid); \231ClrBits(TabEnt->Width); \232} while (0)233#define LOOKUP16(wid,tab,eoflab) do { \234NeedBits16(wid,eoflab); \235TabEnt = tab + GetBits(wid); \236ClrBits(TabEnt->Width); \237} while (0)238239/*240* Append a run to the run length array for the241* current row and reset decoding state.242*/243#define SETVALUE(x) do { \244*pa++ = RunLength + (x); \245a0 += (x); \246RunLength = 0; \247} while (0)248#endif249250/*251* Synchronize input decoding at the start of each252* row by scanning for an EOL (if appropriate) and253* skipping any trash data that might be present254* after a decoding error. Note that the decoding255* done elsewhere that recognizes an EOL only consumes256* 11 consecutive zero bits. This means that if EOLcnt257* is non-zero then we still need to scan for the final flag258* bit that is part of the EOL code.259*/260#define SYNC_EOL(eoflab) do { \261if (EOLcnt == 0) { \262for (;;) { \263NeedBits16(11,eoflab); \264if (GetBits(11) == 0) \265break; \266ClrBits(1); \267} \268} \269for (;;) { \270NeedBits8(8,eoflab); \271if (GetBits(8)) \272break; \273ClrBits(8); \274} \275while (GetBits(1) == 0) \276ClrBits(1); \277ClrBits(1); /* EOL bit */ \278EOLcnt = 0; /* reset EOL counter/flag */ \279} while (0)280281/*282* Cleanup the array of runs after decoding a row.283* We adjust final runs to insure the user buffer is not284* overwritten and/or undecoded area is white filled.285*/286#define CLEANUP_RUNS() do { \287if (RunLength) \288SETVALUE(0); \289if (a0 != lastx) { \290badlength(a0, lastx); \291while (a0 > lastx && pa > thisrun) \292a0 -= *--pa; \293if (a0 < lastx) { \294if (a0 < 0) \295a0 = 0; \296if ((pa-thisrun)&1) \297SETVALUE(0); \298SETVALUE(lastx - a0); \299} else if (a0 > lastx) { \300SETVALUE(lastx); \301SETVALUE(0); \302} \303} \304} while (0)305306/*307* Decode a line of 1D-encoded data.308*309* The line expanders are written as macros so that they can be reused310* but still have direct access to the local variables of the "calling"311* function.312*313* Note that unlike the original version we have to explicitly test for314* a0 >= lastx after each black/white run is decoded. This is because315* the original code depended on the input data being zero-padded to316* insure the decoder recognized an EOL before running out of data.317*/318#define EXPAND1D(eoflab) do { \319for (;;) { \320for (;;) { \321LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \322switch (TabEnt->State) { \323case S_EOL: \324EOLcnt = 1; \325goto done1d; \326case S_TermW: \327SETVALUE(TabEnt->Param); \328goto doneWhite1d; \329case S_MakeUpW: \330case S_MakeUp: \331a0 += TabEnt->Param; \332RunLength += TabEnt->Param; \333break; \334default: \335unexpected("WhiteTable", a0); \336goto done1d; \337} \338} \339doneWhite1d: \340if (a0 >= lastx) \341goto done1d; \342for (;;) { \343LOOKUP16(13, TIFFFaxBlackTable, eof1d); \344switch (TabEnt->State) { \345case S_EOL: \346EOLcnt = 1; \347goto done1d; \348case S_TermB: \349SETVALUE(TabEnt->Param); \350goto doneBlack1d; \351case S_MakeUpB: \352case S_MakeUp: \353a0 += TabEnt->Param; \354RunLength += TabEnt->Param; \355break; \356default: \357unexpected("BlackTable", a0); \358goto done1d; \359} \360} \361doneBlack1d: \362if (a0 >= lastx) \363goto done1d; \364if( *(pa-1) == 0 && *(pa-2) == 0 ) \365pa -= 2; \366} \367eof1d: \368prematureEOF(a0); \369CLEANUP_RUNS(); \370goto eoflab; \371done1d: \372CLEANUP_RUNS(); \373} while (0)374375/*376* Update the value of b1 using the array377* of runs for the reference line.378*/379#define CHECK_b1 do { \380if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \381b1 += pb[0] + pb[1]; \382pb += 2; \383} \384} while (0)385386/*387* Expand a row of 2D-encoded data.388*/389#define EXPAND2D(eoflab) do { \390while (a0 < lastx) { \391LOOKUP8(7, TIFFFaxMainTable, eof2d); \392switch (TabEnt->State) { \393case S_Pass: \394CHECK_b1; \395b1 += *pb++; \396RunLength += b1 - a0; \397a0 = b1; \398b1 += *pb++; \399break; \400case S_Horiz: \401if ((pa-thisrun)&1) { \402for (;;) { /* black first */ \403LOOKUP16(13, TIFFFaxBlackTable, eof2d); \404switch (TabEnt->State) { \405case S_TermB: \406SETVALUE(TabEnt->Param); \407goto doneWhite2da; \408case S_MakeUpB: \409case S_MakeUp: \410a0 += TabEnt->Param; \411RunLength += TabEnt->Param; \412break; \413default: \414goto badBlack2d; \415} \416} \417doneWhite2da:; \418for (;;) { /* then white */ \419LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \420switch (TabEnt->State) { \421case S_TermW: \422SETVALUE(TabEnt->Param); \423goto doneBlack2da; \424case S_MakeUpW: \425case S_MakeUp: \426a0 += TabEnt->Param; \427RunLength += TabEnt->Param; \428break; \429default: \430goto badWhite2d; \431} \432} \433doneBlack2da:; \434} else { \435for (;;) { /* white first */ \436LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \437switch (TabEnt->State) { \438case S_TermW: \439SETVALUE(TabEnt->Param); \440goto doneWhite2db; \441case S_MakeUpW: \442case S_MakeUp: \443a0 += TabEnt->Param; \444RunLength += TabEnt->Param; \445break; \446default: \447goto badWhite2d; \448} \449} \450doneWhite2db:; \451for (;;) { /* then black */ \452LOOKUP16(13, TIFFFaxBlackTable, eof2d); \453switch (TabEnt->State) { \454case S_TermB: \455SETVALUE(TabEnt->Param); \456goto doneBlack2db; \457case S_MakeUpB: \458case S_MakeUp: \459a0 += TabEnt->Param; \460RunLength += TabEnt->Param; \461break; \462default: \463goto badBlack2d; \464} \465} \466doneBlack2db:; \467} \468CHECK_b1; \469break; \470case S_V0: \471CHECK_b1; \472SETVALUE(b1 - a0); \473b1 += *pb++; \474break; \475case S_VR: \476CHECK_b1; \477SETVALUE(b1 - a0 + TabEnt->Param); \478b1 += *pb++; \479break; \480case S_VL: \481CHECK_b1; \482if (b1 <= (int) (a0 + TabEnt->Param)) { \483if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) { \484unexpected("VL", a0); \485goto eol2d; \486} \487} \488SETVALUE(b1 - a0 - TabEnt->Param); \489b1 -= *--pb; \490break; \491case S_Ext: \492*pa++ = lastx - a0; \493extension(a0); \494goto eol2d; \495case S_EOL: \496*pa++ = lastx - a0; \497NeedBits8(4,eof2d); \498if (GetBits(4)) \499unexpected("EOL", a0); \500ClrBits(4); \501EOLcnt = 1; \502goto eol2d; \503default: \504badMain2d: \505unexpected("MainTable", a0); \506goto eol2d; \507badBlack2d: \508unexpected("BlackTable", a0); \509goto eol2d; \510badWhite2d: \511unexpected("WhiteTable", a0); \512goto eol2d; \513eof2d: \514prematureEOF(a0); \515CLEANUP_RUNS(); \516goto eoflab; \517} \518} \519if (RunLength) { \520if (RunLength + a0 < lastx) { \521/* expect a final V0 */ \522NeedBits8(1,eof2d); \523if (!GetBits(1)) \524goto badMain2d; \525ClrBits(1); \526} \527SETVALUE(0); \528} \529eol2d: \530CLEANUP_RUNS(); \531} while (0)532#endif /* _FAX3_ */533/*534* Local Variables:535* mode: c536* c-basic-offset: 8537* fill-column: 78538* End:539*/540541542