1/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam 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 */
55typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
56
57/*
58 * The default run filler; made external for other decoders.
59 */
60#if defined(__cplusplus)
61extern "C" {
62#endif
63extern 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
84typedef 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
90extern const TIFFFaxTabEnt TIFFFaxMainTable[];
91extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
92extern 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
179static 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 SETVALUE(x) do {							\
221    *pa++ = RunLength + (x);						\
222    printf("SETVALUE: %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 SETVALUE(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    SETVALUE(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        SETVALUE(0);						\
297        SETVALUE(lastx - a0);						\
298    } else if (a0 > lastx) {					\
299        SETVALUE(lastx);						\
300        SETVALUE(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        SETVALUE(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        SETVALUE(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        if( *(pa-1) == 0 && *(pa-2) == 0 )				\
364            pa -= 2;                                                    \
365    }									\
366eof1d:									\
367    prematureEOF(a0);							\
368    CLEANUP_RUNS();							\
369    goto eoflab;							\
370done1d:									\
371    CLEANUP_RUNS();							\
372} while (0)
373
374/*
375 * Update the value of b1 using the array
376 * of runs for the reference line.
377 */
378#define CHECK_b1 do {							\
379    if (pa != thisrun) while (b1 <= a0 && b1 < lastx) {			\
380    b1 += pb[0] + pb[1];						\
381    pb += 2;							\
382    }									\
383} while (0)
384
385/*
386 * Expand a row of 2D-encoded data.
387 */
388#define EXPAND2D(eoflab) do {						\
389    while (a0 < lastx) {						\
390    LOOKUP8(7, TIFFFaxMainTable, eof2d);				\
391    switch (TabEnt->State) {					\
392    case S_Pass:							\
393        CHECK_b1;							\
394        b1 += *pb++;						\
395        RunLength += b1 - a0;					\
396        a0 = b1;							\
397        b1 += *pb++;						\
398        break;							\
399    case S_Horiz:							\
400        if ((pa-thisrun)&1) {					\
401        for (;;) {	/* black first */			\
402            LOOKUP16(13, TIFFFaxBlackTable, eof2d);		\
403            switch (TabEnt->State) {				\
404            case S_TermB:					\
405            SETVALUE(TabEnt->Param);				\
406            goto doneWhite2da;				\
407            case S_MakeUpB:					\
408            case S_MakeUp:					\
409            a0 += TabEnt->Param;				\
410            RunLength += TabEnt->Param;			\
411            break;						\
412            default:						\
413            goto badBlack2d;				\
414            }							\
415        }							\
416        doneWhite2da:;						\
417        for (;;) {	/* then white */			\
418            LOOKUP16(12, TIFFFaxWhiteTable, eof2d);		\
419            switch (TabEnt->State) {				\
420            case S_TermW:					\
421            SETVALUE(TabEnt->Param);				\
422            goto doneBlack2da;				\
423            case S_MakeUpW:					\
424            case S_MakeUp:					\
425            a0 += TabEnt->Param;				\
426            RunLength += TabEnt->Param;			\
427            break;						\
428            default:						\
429            goto badWhite2d;				\
430            }							\
431        }							\
432        doneBlack2da:;						\
433        } else {							\
434        for (;;) {	/* white first */			\
435            LOOKUP16(12, TIFFFaxWhiteTable, eof2d);		\
436            switch (TabEnt->State) {				\
437            case S_TermW:					\
438            SETVALUE(TabEnt->Param);				\
439            goto doneWhite2db;				\
440            case S_MakeUpW:					\
441            case S_MakeUp:					\
442            a0 += TabEnt->Param;				\
443            RunLength += TabEnt->Param;			\
444            break;						\
445            default:						\
446            goto badWhite2d;				\
447            }							\
448        }							\
449        doneWhite2db:;						\
450        for (;;) {	/* then black */			\
451            LOOKUP16(13, TIFFFaxBlackTable, eof2d);		\
452            switch (TabEnt->State) {				\
453            case S_TermB:					\
454            SETVALUE(TabEnt->Param);				\
455            goto doneBlack2db;				\
456            case S_MakeUpB:					\
457            case S_MakeUp:					\
458            a0 += TabEnt->Param;				\
459            RunLength += TabEnt->Param;			\
460            break;						\
461            default:						\
462            goto badBlack2d;				\
463            }							\
464        }							\
465        doneBlack2db:;						\
466        }								\
467        CHECK_b1;							\
468        break;							\
469    case S_V0:							\
470        CHECK_b1;							\
471        SETVALUE(b1 - a0);						\
472        b1 += *pb++;						\
473        break;							\
474    case S_VR:							\
475        CHECK_b1;							\
476        SETVALUE(b1 - a0 + TabEnt->Param);				\
477        b1 += *pb++;						\
478        break;							\
479    case S_VL:							\
480        CHECK_b1;							\
481        if (b1 <= (int) (a0 + TabEnt->Param)) {			\
482        if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) {	\
483            unexpected("VL", a0);				\
484            goto eol2d;						\
485        }							\
486        }								\
487        SETVALUE(b1 - a0 - TabEnt->Param);				\
488        b1 -= *--pb;						\
489        break;							\
490    case S_Ext:							\
491        *pa++ = lastx - a0;						\
492        extension(a0);						\
493        goto eol2d;							\
494    case S_EOL:							\
495        *pa++ = lastx - a0;						\
496        NeedBits8(4,eof2d);						\
497        if (GetBits(4))						\
498        unexpected("EOL", a0);					\
499            ClrBits(4);                                                 \
500        EOLcnt = 1;							\
501        goto eol2d;							\
502    default:							\
503    badMain2d:							\
504        unexpected("MainTable", a0);				\
505        goto eol2d;							\
506    badBlack2d:							\
507        unexpected("BlackTable", a0);				\
508        goto eol2d;							\
509    badWhite2d:							\
510        unexpected("WhiteTable", a0);				\
511        goto eol2d;							\
512    eof2d:								\
513        prematureEOF(a0);						\
514        CLEANUP_RUNS();						\
515        goto eoflab;						\
516    }								\
517    }									\
518    if (RunLength) {							\
519    if (RunLength + a0 < lastx) {					\
520        /* expect a final V0 */					\
521        NeedBits8(1,eof2d);						\
522        if (!GetBits(1))						\
523        goto badMain2d;						\
524        ClrBits(1);							\
525    }								\
526    SETVALUE(0);							\
527    }									\
528eol2d:									\
529    CLEANUP_RUNS();							\
530} while (0)
531#endif /* _FAX3_ */
532/*
533 * Local Variables:
534 * mode: c
535 * c-basic-offset: 8
536 * fill-column: 78
537 * End:
538 */
539