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