4 * Copyright (c) 1990-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
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.
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.
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
32 * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
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.
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;
46 * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
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).
55 typedef void (*TIFFFaxFillFunc
)(unsigned char*, uint32
*, uint32
*, uint32
);
58 * The default run filler; made external for other decoders.
60 #if defined(__cplusplus)
63 extern void _TIFFFax3fillruns(unsigned char*, uint32
*, uint32
*, uint32
);
64 #if defined(__cplusplus)
69 /* finite state machine codes */
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 */
90 extern const TIFFFaxTabEnt TIFFFaxMainTable
[];
91 extern const TIFFFaxTabEnt TIFFFaxWhiteTable
[];
92 extern const TIFFFaxTabEnt TIFFFaxBlackTable
[];
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).
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.
106 * NB: to enable a debugging version of these macros define FAX3_DEBUG
107 * before including this file. Trace output goes to stdout.
111 #define EndOfData() (cp >= ep)
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.
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.
137 #define NeedBits8(n,eoflab) do { \
138 if (BitsAvail < (n)) { \
140 if (BitsAvail == 0) /* no valid bits */ \
142 BitsAvail = (n); /* pad with zeros */ \
144 BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
151 #define NeedBits16(n,eoflab) do { \
152 if (BitsAvail < (n)) { \
154 if (BitsAvail == 0) /* no valid bits */ \
156 BitsAvail = (n); /* pad with zeros */ \
158 BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
159 if ((BitsAvail += 8) < (n)) { \
161 /* NB: we know BitsAvail is non-zero here */ \
162 BitsAvail = (n); /* pad with zeros */ \
164 BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
172 #define GetBits(n) (BitAcc & ((1<<(n))-1))
173 #define ClrBits(n) do { \
179 static const char* StateNames
[] = {
194 #define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
195 #define LOOKUP8(wid,tab,eoflab) do { \
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++) \
205 ClrBits(TabEnt->Width); \
207 #define LOOKUP16(wid,tab,eoflab) do { \
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++) \
217 ClrBits(TabEnt->Width); \
220 #define SETVAL(x) do { \
221 *pa++ = RunLength + (x); \
222 printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \
227 #define LOOKUP8(wid,tab,eoflab) do { \
228 NeedBits8(wid,eoflab); \
229 TabEnt = tab + GetBits(wid); \
230 ClrBits(TabEnt->Width); \
232 #define LOOKUP16(wid,tab,eoflab) do { \
233 NeedBits16(wid,eoflab); \
234 TabEnt = tab + GetBits(wid); \
235 ClrBits(TabEnt->Width); \
239 * Append a run to the run length array for the
240 * current row and reset decoding state.
242 #define SETVAL(x) do { \
243 *pa++ = RunLength + (x); \
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.
259 #define SYNC_EOL(eoflab) do { \
262 NeedBits16(11,eoflab); \
263 if (GetBits(11) == 0) \
269 NeedBits8(8,eoflab); \
274 while (GetBits(1) == 0) \
276 ClrBits(1); /* EOL bit */ \
277 EOLcnt = 0; /* reset EOL counter/flag */ \
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.
285 #define CLEANUP_RUNS() do { \
289 badlength(a0, lastx); \
290 while (a0 > lastx && pa > thisrun) \
295 if ((pa-thisrun)&1) \
297 SETVAL(lastx - a0); \
298 } else if (a0 > lastx) { \
306 * Decode a line of 1D-encoded data.
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"
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.
317 #define EXPAND1D(eoflab) do { \
320 LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \
321 switch (TabEnt->State) { \
326 SETVAL(TabEnt->Param); \
330 a0 += TabEnt->Param; \
331 RunLength += TabEnt->Param; \
334 unexpected("WhiteTable", a0); \
342 LOOKUP16(13, TIFFFaxBlackTable, eof1d); \
343 switch (TabEnt->State) { \
348 SETVAL(TabEnt->Param); \
352 a0 += TabEnt->Param; \
353 RunLength += TabEnt->Param; \
356 unexpected("BlackTable", a0); \
363 if( *(pa-1) == 0 && *(pa-2) == 0 ) \
375 * Update the value of b1 using the array
376 * of runs for the reference line.
378 #define CHECK_b1 do { \
379 if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \
380 b1 += pb[0] + pb[1]; \
386 * Expand a row of 2D-encoded data.
388 #define EXPAND2D(eoflab) do { \
389 while (a0 < lastx) { \
390 LOOKUP8(7, TIFFFaxMainTable, eof2d); \
391 switch (TabEnt->State) { \
395 RunLength += b1 - a0; \
400 if ((pa-thisrun)&1) { \
401 for (;;) { /* black first */ \
402 LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
403 switch (TabEnt->State) { \
405 SETVAL(TabEnt->Param); \
409 a0 += TabEnt->Param; \
410 RunLength += TabEnt->Param; \
417 for (;;) { /* then white */ \
418 LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
419 switch (TabEnt->State) { \
421 SETVAL(TabEnt->Param); \
425 a0 += TabEnt->Param; \
426 RunLength += TabEnt->Param; \
434 for (;;) { /* white first */ \
435 LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
436 switch (TabEnt->State) { \
438 SETVAL(TabEnt->Param); \
442 a0 += TabEnt->Param; \
443 RunLength += TabEnt->Param; \
450 for (;;) { /* then black */ \
451 LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
452 switch (TabEnt->State) { \
454 SETVAL(TabEnt->Param); \
458 a0 += TabEnt->Param; \
459 RunLength += TabEnt->Param; \
476 SETVAL(b1 - a0 + TabEnt->Param); \
481 SETVAL(b1 - a0 - TabEnt->Param); \
485 *pa++ = lastx - a0; \
489 *pa++ = lastx - a0; \
490 NeedBits8(4,eof2d); \
492 unexpected("EOL", a0); \
498 unexpected("MainTable", a0); \
501 unexpected("BlackTable", a0); \
504 unexpected("WhiteTable", a0); \
513 if (RunLength + a0 < lastx) { \
514 /* expect a final V0 */ \
515 NeedBits8(1,eof2d); \