PageRenderTime 24ms CodeModel.GetById 16ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibTIFF/tif_fax3.h

https://bitbucket.org/cabalistic/ogredeps/
C++ Header | 538 lines | 385 code | 18 blank | 135 comment | 83 complexity | fadd81983aae6d784a1eecbeb40fa253 MD5 | raw file
  1/* $Id: tif_fax3.h,v 1.37 2011/04/10 17:14:09 drolon 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 */