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