File: G3Decoder.c%2B%2B

package info (click to toggle)
hylafax 1%3A4.2.1-5sarge3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 6,788 kB
  • ctags: 7,523
  • sloc: sh: 15,597; ansic: 13,040; makefile: 1,772; cpp: 864
file content (272 lines) | stat: -rw-r--r-- 7,382 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*	$Id: G3Decoder.c++,v 1.8 2003/12/11 18:43:32 lhoward Exp $ */
/*
 * Copyright (c) 1994-1996 Sam Leffler
 * Copyright (c) 1994-1996 Silicon Graphics, Inc.
 * HylaFAX is a trademark of Silicon Graphics
 *
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Sam Leffler and Silicon Graphics.
 * 
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 * 
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 * OF THIS SOFTWARE.
 */

/*
 * Group 3 Facsimile Reader Support.
 */
#include "G3Decoder.h"

/*
 * These macros glue the G3Decoder state to
 * the state expected by Frank Cringle's decoder.
 */
#define	DECLARE_STATE_EOL()						\
    uint32 BitAcc;			/* bit accumulator */		\
    int BitsAvail;			/* # valid bits in BitAcc */	\
    int EOLcnt				/* # EOL codes recognized */
#define	DECLARE_STATE()							\
    DECLARE_STATE_EOL();						\
    int a0;				/* reference element */		\
    int RunLength;			/* length of current run */	\
    tiff_runlen_t* pa;			/* place to stuff next run */	\
    tiff_runlen_t* thisrun;			/* current row's run array */	\
    const TIFFFaxTabEnt* TabEnt
#define	DECLARE_STATE_2D()						\
    DECLARE_STATE();							\
    int b1;				/* next change on prev line */	\
    tiff_runlen_t* pb			/* next run in reference line */
/*
 * Load any state that may be changed during decoding.
 */
#define	CACHE_STATE() do {						\
    BitAcc = data;							\
    BitsAvail = bit;							\
    EOLcnt = this->EOLcnt;						\
} while (0)
/*
 * Save state possibly changed during decoding.
 */
#define	UNCACHE_STATE() do {						\
    bit = BitsAvail;							\
    data = BitAcc;							\
    this->EOLcnt = EOLcnt;						\
} while (0)

/*
 * Override default definitions for the TIFF library.
 * We redirect the logic to call nextByte for each
 * input byte we need.  Note that we don't need to check
 * for EOF because the input decoder does a longjmp.
 */
#define NeedBits8(n,eoflab) do {					\
    if (BitsAvail < (n)) {						\
	BitAcc |= nextByte()<<BitsAvail;				\
	BitsAvail += 8;							\
    }									\
} while (0)
#define NeedBits16(n,eoflab) do {					\
    if (BitsAvail < (n)) {						\
	BitAcc |= nextByte()<<BitsAvail;				\
	if ((BitsAvail += 8) < (n)) {					\
	    BitAcc |= nextByte()<<BitsAvail;				\
	    BitsAvail += 8;						\
	}								\
    }									\
} while (0)

#include "tif_fax3.h"

G3Decoder::G3Decoder() {}
G3Decoder::~G3Decoder() {}

void
G3Decoder::setupDecoder(u_int recvFillOrder, bool is2d, bool isg4)
{
    /*
     * The G3 decoding state tables are constructed for
     * data in LSB2MSB bit order.  Received data that
     * is not in this order is reversed using the
     * appropriate byte-wide bit-reversal table.
     */
    is2D = is2d;
    isG4 = isg4;
    bitmap = TIFFGetBitRevTable(recvFillOrder != FILLORDER_LSB2MSB);
    data = 0;					// not needed
    bit = 0;					// force initial read
    EOLcnt = 0;					// no initial EOL
    RTCrun = 0;					// reset run count
    RTCrow = -1;				// reset RTC row number
    rowref = 0;					// reset row count
    curruns = refruns = NULL;
}

void
G3Decoder::setRuns(tiff_runlen_t* cr, tiff_runlen_t* rr, int w)
{
    curruns = cr;
    if ((refruns = rr)) {
	refruns[0] = w;
	refruns[1] = 0;
    }
}

void G3Decoder::raiseEOF()	{ siglongjmp(jmpEOF, 1); }
void G3Decoder::raiseRTC()	{ siglongjmp(jmpRTC, 1); }

/*
 * Decode h rows that are w pixels wide and return
 * the decoded data in raster.
 */
void
G3Decoder::decode(void* raster, u_int w, u_int h)
{
    u_int rowbytes = howmany(w, 8);
    if (curruns == NULL) {
	tiff_runlen_t runs[2*4864];		// run arrays for cur+ref rows
	setRuns(runs, runs+4864, w);
	while (h-- > 0) {
	    decodeRow(raster, w);
	    if (raster)
		raster = (u_char*) raster + rowbytes;
	}
    } else {
	while (h-- > 0) {
	    decodeRow(raster, w);
	    if (raster)
		raster = (u_char*) raster + rowbytes;
	}
    }
}

bool
G3Decoder::isNextRow1D()
{
    DECLARE_STATE_EOL();

    CACHE_STATE();
    SYNC_EOL(Nop);
    bool is1D;
    if (is2D) {
	NeedBits8(1, Nop);
	is1D = (GetBits(1) != 0);	// 1D/2D-encoding tag bit
	// NB: we don't clear the tag bit
    } else {
	is1D = true;
    }
    // now reset state for next decoded row
    BitAcc = (BitAcc<<1)|1;		// EOL bit
    BitsAvail++;
    EOLcnt = 1;				// mark state to indicate EOL recognized
    UNCACHE_STATE();
    return (is1D);
}

#define	unexpected(table, a0) do {		\
    invalidCode(table, a0);			\
    rowgood = false;				\
} while (0)
#define	extension(a0) do {			\
    invalidCode("2D", a0);			\
    rowgood = false;				\
} while (0)
#define	prematureEOF(a0)	// never happens 'cuz of longjmp
#define	SWAP(t,a,b)	{ t x; x = (a); (a) = (b); (b) = x; }

/*
 * Decode a single row of pixels and return
 * the decoded data in the scanline buffer.
 */
bool
G3Decoder::decodeRow(void* scanline, u_int lastx)
{
    DECLARE_STATE_2D();
    bool rowgood = true;
    bool nullrow = false;

    CACHE_STATE();
    a0 = 0;
    RunLength = 0;
    pa = thisrun = curruns;
    bool is1D;
    if (isG4) {
	is1D = false;
    } else {
	SYNC_EOL(Nop);
	if (is2D) {
	    NeedBits8(1, Nop);
	    is1D = (GetBits(1) != 0);	// 1D/2D-encoding tag bit
	    ClrBits(1);
	} else
	    is1D = true;
    }
    if (!is1D) {
	pb = refruns;
	b1 = *pb++;
#define	badlength(a0,lastx) do {			\
    if (isG4)						\
	RTCrow = rowref;				\
    badPixelCount("2D", a0, lastx);			\
    rowgood = false;					\
} while (0)
	EXPAND2D(Nop2d);
    Nop2d:;
#undef	badlength
    } else {
#define	badlength(a0,lastx) do {			\
    nullrow = (a0 == 0);				\
    if (nullrow && ++RTCrun == 5 && RTCrow == -1)	\
	RTCrow = rowref-4;				\
    badPixelCount("1D", a0, lastx);			\
    rowgood = false;					\
} while (0)
	EXPAND1D(Nop1d);
    Nop1d:;
#undef	badlength
    }
    if (!nullrow)
	RTCrun = 0;
    if (scanline)
	_TIFFFax3fillruns((u_char*) scanline, thisrun, pa, lastx);
    if (is2D) {
	SETVAL(0);			// imaginary change for reference
	SWAP(tiff_runlen_t*, curruns, refruns);
    }
    rowref++;
    UNCACHE_STATE();
    return (rowgood);
}

#undef	SWAP
#undef	prematureEOF
#undef	extension
#undef	unexpected

/*
 * Return the next decoded byte of page data from
 * the input stream.  The byte is returned in the
 * bit order required by the G3 decoder.
 */
int
G3Decoder::nextByte()
{
    return bitmap[decodeNextByte()];
}

int G3Decoder::decodeNextByte() { raiseEOF(); return (0); }

void G3Decoder::invalidCode(const char*, int) {}
void G3Decoder::badPixelCount(const char*, int, int) {}
void G3Decoder::badDecodingState(const char*, int) {}