Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tiff/libtiff/tif_fax3.h
8855 views
1
/*
2
* Copyright (c) 1990-1997 Sam Leffler
3
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
4
*
5
* Permission to use, copy, modify, distribute, and sell this software and
6
* its documentation for any purpose is hereby granted without fee, provided
7
* that (i) the above copyright notices and this permission notice appear in
8
* all copies of the software and related documentation, and (ii) the names of
9
* Sam Leffler and Silicon Graphics may not be used in any advertising or
10
* publicity relating to the software without the specific, prior written
11
* permission of Sam Leffler and Silicon Graphics.
12
*
13
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16
*
17
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22
* OF THIS SOFTWARE.
23
*/
24
25
#ifndef _FAX3_
26
#define _FAX3_
27
/*
28
* TIFF Library.
29
*
30
* CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
31
*
32
* Decoder support is derived, with permission, from the code
33
* in Frank Cringle's viewfax program;
34
* Copyright (C) 1990, 1995 Frank D. Cringle.
35
*/
36
#include "tiff.h"
37
38
/*
39
* To override the default routine used to image decoded
40
* spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC.
41
* The routine must have the type signature given below;
42
* for example:
43
*
44
* fillruns(unsigned char* buf, uint32_t* runs, uint32_t* erun, uint32_t lastx)
45
*
46
* where buf is place to set the bits, runs is the array of b&w run
47
* lengths (white then black), erun is the last run in the array, and
48
* lastx is the width of the row in pixels. Fill routines can assume
49
* the run array has room for at least lastx runs and can overwrite
50
* data in the run array as needed (e.g. to append zero runs to bring
51
* the count up to a nice multiple).
52
*/
53
typedef void (*TIFFFaxFillFunc)(unsigned char *, uint32_t *, uint32_t *,
54
uint32_t);
55
56
/*
57
* The default run filler; made external for other decoders.
58
*/
59
#if defined(__cplusplus)
60
extern "C"
61
{
62
#endif
63
extern void _TIFFFax3fillruns(unsigned char *, uint32_t *, uint32_t *,
64
uint32_t);
65
#if defined(__cplusplus)
66
}
67
#endif
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
*/
86
/* really depends on it. See http://bugzilla.maptools.org/show_bug.cgi?id=2636
87
*/
88
typedef struct
89
{ /* state table entry */
90
unsigned char State; /* see above */
91
unsigned char Width; /* width of code in bits */
92
uint32_t Param; /* unsigned 32-bit run length in bits (holds on 16 bit
93
actually, but cannot be changed. See above warning) */
94
} TIFFFaxTabEnt;
95
96
extern const TIFFFaxTabEnt TIFFFaxMainTable[];
97
extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
98
extern const TIFFFaxTabEnt TIFFFaxBlackTable[];
99
100
/*
101
* The following macros define the majority of the G3/G4 decoder
102
* algorithm using the state tables defined elsewhere. To build
103
* a decoder you need some setup code and some glue code. Note
104
* that you may also need/want to change the way the NeedBits*
105
* macros get input data if, for example, you know the data to be
106
* decoded is properly aligned and oriented (doing so before running
107
* the decoder can be a big performance win).
108
*
109
* Consult the decoder in the TIFF library for an idea of what you
110
* need to define and setup to make use of these definitions.
111
*
112
* NB: to enable a debugging version of these macros define FAX3_DEBUG
113
* before including this file. Trace output goes to stdout.
114
*/
115
116
#ifndef EndOfData
117
#define EndOfData() (cp >= ep)
118
#endif
119
/*
120
* Need <=8 or <=16 bits of input data. Unlike viewfax we
121
* cannot use/assume a word-aligned, properly bit swizzled
122
* input data set because data may come from an arbitrarily
123
* aligned, read-only source such as a memory-mapped file.
124
* Note also that the viewfax decoder does not check for
125
* running off the end of the input data buffer. This is
126
* possible for G3-encoded data because it prescans the input
127
* data to count EOL markers, but can cause problems for G4
128
* data. In any event, we don't prescan and must watch for
129
* running out of data since we can't permit the library to
130
* scan past the end of the input data buffer.
131
*
132
* Finally, note that we must handle remaindered data at the end
133
* of a strip specially. The coder asks for a fixed number of
134
* bits when scanning for the next code. This may be more bits
135
* than are actually present in the data stream. If we appear
136
* to run out of data but still have some number of valid bits
137
* remaining then we makeup the requested amount with zeros and
138
* return successfully. If the returned data is incorrect then
139
* we should be called again and get a premature EOF error;
140
* otherwise we should get the right answer.
141
*/
142
#ifndef NeedBits8
143
#define NeedBits8(n, eoflab) \
144
do \
145
{ \
146
if (BitsAvail < (n)) \
147
{ \
148
if (EndOfData()) \
149
{ \
150
if (BitsAvail == 0) /* no valid bits */ \
151
goto eoflab; \
152
BitsAvail = (n); /* pad with zeros */ \
153
} \
154
else \
155
{ \
156
BitAcc |= ((uint32_t)bitmap[*cp++]) << BitsAvail; \
157
BitsAvail += 8; \
158
} \
159
} \
160
} while (0)
161
#endif
162
#ifndef NeedBits16
163
#define NeedBits16(n, eoflab) \
164
do \
165
{ \
166
if (BitsAvail < (n)) \
167
{ \
168
if (EndOfData()) \
169
{ \
170
if (BitsAvail == 0) /* no valid bits */ \
171
goto eoflab; \
172
BitsAvail = (n); /* pad with zeros */ \
173
} \
174
else \
175
{ \
176
BitAcc |= ((uint32_t)bitmap[*cp++]) << BitsAvail; \
177
if ((BitsAvail += 8) < (n)) \
178
{ \
179
if (EndOfData()) \
180
{ \
181
/* NB: we know BitsAvail is non-zero here */ \
182
BitsAvail = (n); /* pad with zeros */ \
183
} \
184
else \
185
{ \
186
BitAcc |= ((uint32_t)bitmap[*cp++]) << BitsAvail; \
187
BitsAvail += 8; \
188
} \
189
} \
190
} \
191
} \
192
} while (0)
193
#endif
194
#define GetBits(n) (BitAcc & ((1 << (n)) - 1))
195
#define ClrBits(n) \
196
do \
197
{ \
198
BitsAvail -= (n); \
199
BitAcc >>= (n); \
200
} while (0)
201
202
#ifdef FAX3_DEBUG
203
static const char *StateNames[] = {
204
"Null ", "Pass ", "Horiz ", "V0 ", "VR ", "VL ", "Ext ",
205
"TermW ", "TermB ", "MakeUpW", "MakeUpB", "MakeUp ", "EOL ",
206
};
207
#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
208
#define LOOKUP8(wid, tab, eoflab) \
209
do \
210
{ \
211
int t; \
212
NeedBits8(wid, eoflab); \
213
TabEnt = tab + GetBits(wid); \
214
printf("%08lX/%d: %s%5d\t", (long)BitAcc, BitsAvail, \
215
StateNames[TabEnt->State], TabEnt->Param); \
216
for (t = 0; t < TabEnt->Width; t++) \
217
DEBUG_SHOW; \
218
putchar('\n'); \
219
fflush(stdout); \
220
ClrBits(TabEnt->Width); \
221
} while (0)
222
#define LOOKUP16(wid, tab, eoflab) \
223
do \
224
{ \
225
int t; \
226
NeedBits16(wid, eoflab); \
227
TabEnt = tab + GetBits(wid); \
228
printf("%08lX/%d: %s%5d\t", (long)BitAcc, BitsAvail, \
229
StateNames[TabEnt->State], TabEnt->Param); \
230
for (t = 0; t < TabEnt->Width; t++) \
231
DEBUG_SHOW; \
232
putchar('\n'); \
233
fflush(stdout); \
234
ClrBits(TabEnt->Width); \
235
} while (0)
236
237
#define SETVALUE(x) \
238
do \
239
{ \
240
*pa++ = RunLength + (x); \
241
printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \
242
a0 += x; \
243
RunLength = 0; \
244
} while (0)
245
#else
246
#define LOOKUP8(wid, tab, eoflab) \
247
do \
248
{ \
249
NeedBits8(wid, eoflab); \
250
TabEnt = tab + GetBits(wid); \
251
ClrBits(TabEnt->Width); \
252
} while (0)
253
#define LOOKUP16(wid, tab, eoflab) \
254
do \
255
{ \
256
NeedBits16(wid, eoflab); \
257
TabEnt = tab + GetBits(wid); \
258
ClrBits(TabEnt->Width); \
259
} while (0)
260
261
/*
262
* Append a run to the run length array for the
263
* current row and reset decoding state.
264
*/
265
#define SETVALUE(x) \
266
do \
267
{ \
268
if (pa >= thisrun + sp->nruns) \
269
{ \
270
TIFFErrorExtR(tif, module, "Buffer overflow at line %u of %s %u", \
271
sp->line, isTiled(tif) ? "tile" : "strip", \
272
isTiled(tif) ? tif->tif_curtile \
273
: tif->tif_curstrip); \
274
return (-1); \
275
} \
276
*pa++ = RunLength + (x); \
277
a0 += (x); \
278
RunLength = 0; \
279
} while (0)
280
#endif
281
282
/*
283
* Synchronize input decoding at the start of each
284
* row by scanning for an EOL (if appropriate) and
285
* skipping any trash data that might be present
286
* after a decoding error. Note that the decoding
287
* done elsewhere that recognizes an EOL only consumes
288
* 11 consecutive zero bits. This means that if EOLcnt
289
* is non-zero then we still need to scan for the final flag
290
* bit that is part of the EOL code.
291
*/
292
#define SYNC_EOL(eoflab, retrywithouteol) \
293
do \
294
{ \
295
if (!(sp->b.mode & FAXMODE_NOEOL)) /* skip EOL, if not present */ \
296
{ \
297
if (EOLcnt == 0) \
298
{ \
299
for (;;) \
300
{ \
301
NeedBits16(11, eoflab); \
302
if (GetBits(11) == 0) \
303
break; /* EOL found */ \
304
ClrBits(1); \
305
} \
306
} \
307
/* Now move after EOL or detect missing EOL. */ \
308
for (;;) \
309
{ \
310
NeedBits8(8, noEOLFound); \
311
if (GetBits(8)) \
312
break; \
313
ClrBits(8); \
314
} \
315
while (GetBits(1) == 0) \
316
ClrBits(1); \
317
ClrBits(1); /* EOL bit */ \
318
EOLcnt = 0; /* reset EOL counter/flag */ \
319
break; /* existing EOL skipped, leave macro */ \
320
noEOLFound: \
321
sp->b.mode |= FAXMODE_NOEOL; \
322
tryG3WithoutEOL(a0); \
323
goto retrywithouteol; \
324
} \
325
} while (0)
326
327
/*
328
* Cleanup the array of runs after decoding a row.
329
* We adjust final runs to insure the user buffer is not
330
* overwritten and/or undecoded area is white filled.
331
*/
332
#define CLEANUP_RUNS() \
333
do \
334
{ \
335
if (RunLength) \
336
SETVALUE(0); \
337
if (a0 != lastx) \
338
{ \
339
badlength(a0, lastx); \
340
while (a0 > lastx && pa > thisrun) \
341
a0 -= *--pa; \
342
if (a0 < lastx) \
343
{ \
344
if (a0 < 0) \
345
a0 = 0; \
346
if ((pa - thisrun) & 1) \
347
SETVALUE(0); \
348
SETVALUE(lastx - a0); \
349
} \
350
else if (a0 > lastx) \
351
{ \
352
SETVALUE(lastx); \
353
SETVALUE(0); \
354
} \
355
} \
356
} while (0)
357
358
/*
359
* Decode a line of 1D-encoded data.
360
*
361
* The line expanders are written as macros so that they can be reused
362
* but still have direct access to the local variables of the "calling"
363
* function.
364
*
365
* Note that unlike the original version we have to explicitly test for
366
* a0 >= lastx after each black/white run is decoded. This is because
367
* the original code depended on the input data being zero-padded to
368
* insure the decoder recognized an EOL before running out of data.
369
*/
370
#define EXPAND1D(eoflab) \
371
do \
372
{ \
373
for (;;) \
374
{ \
375
for (;;) \
376
{ \
377
LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \
378
switch (TabEnt->State) \
379
{ \
380
case S_EOL: \
381
EOLcnt = 1; \
382
goto done1d; \
383
case S_TermW: \
384
SETVALUE(TabEnt->Param); \
385
goto doneWhite1d; \
386
case S_MakeUpW: \
387
case S_MakeUp: \
388
a0 += TabEnt->Param; \
389
RunLength += TabEnt->Param; \
390
break; \
391
default: \
392
unexpected("WhiteTable", a0); \
393
goto done1d; \
394
} \
395
} \
396
doneWhite1d: \
397
if (a0 >= lastx) \
398
goto done1d; \
399
for (;;) \
400
{ \
401
LOOKUP16(13, TIFFFaxBlackTable, eof1d); \
402
switch (TabEnt->State) \
403
{ \
404
case S_EOL: \
405
EOLcnt = 1; \
406
goto done1d; \
407
case S_TermB: \
408
SETVALUE(TabEnt->Param); \
409
goto doneBlack1d; \
410
case S_MakeUpB: \
411
case S_MakeUp: \
412
a0 += TabEnt->Param; \
413
RunLength += TabEnt->Param; \
414
break; \
415
default: \
416
unexpected("BlackTable", a0); \
417
goto done1d; \
418
} \
419
} \
420
doneBlack1d: \
421
if (a0 >= lastx) \
422
goto done1d; \
423
if (*(pa - 1) == 0 && *(pa - 2) == 0) \
424
pa -= 2; \
425
} \
426
eof1d: \
427
prematureEOF(a0); \
428
CLEANUP_RUNS(); \
429
goto eoflab; \
430
done1d: \
431
CLEANUP_RUNS(); \
432
} while (0)
433
434
/*
435
* Update the value of b1 using the array
436
* of runs for the reference line.
437
*/
438
#define CHECK_b1 \
439
do \
440
{ \
441
if (pa != thisrun) \
442
while (b1 <= a0 && b1 < lastx) \
443
{ \
444
if (pb + 1 >= sp->refruns + sp->nruns) \
445
{ \
446
TIFFErrorExtR( \
447
tif, module, "Buffer overflow at line %u of %s %u", \
448
sp->line, isTiled(tif) ? "tile" : "strip", \
449
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip); \
450
return (-1); \
451
} \
452
b1 += pb[0] + pb[1]; \
453
pb += 2; \
454
} \
455
} while (0)
456
457
/*
458
* Expand a row of 2D-encoded data.
459
*/
460
#define EXPAND2D(eoflab) \
461
do \
462
{ \
463
while (a0 < lastx) \
464
{ \
465
if (pa >= thisrun + sp->nruns) \
466
{ \
467
TIFFErrorExtR( \
468
tif, module, "Buffer overflow at line %u of %s %u", \
469
sp->line, isTiled(tif) ? "tile" : "strip", \
470
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip); \
471
return (-1); \
472
} \
473
LOOKUP8(7, TIFFFaxMainTable, eof2d); \
474
switch (TabEnt->State) \
475
{ \
476
case S_Pass: \
477
CHECK_b1; \
478
if (pb + 1 >= sp->refruns + sp->nruns) \
479
{ \
480
TIFFErrorExtR(tif, module, \
481
"Buffer overflow at line %u of %s %u", \
482
sp->line, \
483
isTiled(tif) ? "tile" : "strip", \
484
isTiled(tif) ? tif->tif_curtile \
485
: tif->tif_curstrip); \
486
return (-1); \
487
} \
488
b1 += *pb++; \
489
RunLength += b1 - a0; \
490
a0 = b1; \
491
b1 += *pb++; \
492
break; \
493
case S_Horiz: \
494
if ((pa - thisrun) & 1) \
495
{ \
496
for (;;) \
497
{ /* black first */ \
498
LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
499
switch (TabEnt->State) \
500
{ \
501
case S_TermB: \
502
SETVALUE(TabEnt->Param); \
503
goto doneWhite2da; \
504
case S_MakeUpB: \
505
case S_MakeUp: \
506
a0 += TabEnt->Param; \
507
RunLength += TabEnt->Param; \
508
break; \
509
default: \
510
goto badBlack2d; \
511
} \
512
} \
513
doneWhite2da:; \
514
for (;;) \
515
{ /* then white */ \
516
LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
517
switch (TabEnt->State) \
518
{ \
519
case S_TermW: \
520
SETVALUE(TabEnt->Param); \
521
goto doneBlack2da; \
522
case S_MakeUpW: \
523
case S_MakeUp: \
524
a0 += TabEnt->Param; \
525
RunLength += TabEnt->Param; \
526
break; \
527
default: \
528
goto badWhite2d; \
529
} \
530
} \
531
doneBlack2da:; \
532
} \
533
else \
534
{ \
535
for (;;) \
536
{ /* white first */ \
537
LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
538
switch (TabEnt->State) \
539
{ \
540
case S_TermW: \
541
SETVALUE(TabEnt->Param); \
542
goto doneWhite2db; \
543
case S_MakeUpW: \
544
case S_MakeUp: \
545
a0 += TabEnt->Param; \
546
RunLength += TabEnt->Param; \
547
break; \
548
default: \
549
goto badWhite2d; \
550
} \
551
} \
552
doneWhite2db:; \
553
for (;;) \
554
{ /* then black */ \
555
LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
556
switch (TabEnt->State) \
557
{ \
558
case S_TermB: \
559
SETVALUE(TabEnt->Param); \
560
goto doneBlack2db; \
561
case S_MakeUpB: \
562
case S_MakeUp: \
563
a0 += TabEnt->Param; \
564
RunLength += TabEnt->Param; \
565
break; \
566
default: \
567
goto badBlack2d; \
568
} \
569
} \
570
doneBlack2db:; \
571
} \
572
CHECK_b1; \
573
break; \
574
case S_V0: \
575
CHECK_b1; \
576
SETVALUE(b1 - a0); \
577
if (pb >= sp->refruns + sp->nruns) \
578
{ \
579
TIFFErrorExtR(tif, module, \
580
"Buffer overflow at line %u of %s %u", \
581
sp->line, \
582
isTiled(tif) ? "tile" : "strip", \
583
isTiled(tif) ? tif->tif_curtile \
584
: tif->tif_curstrip); \
585
return (-1); \
586
} \
587
b1 += *pb++; \
588
break; \
589
case S_VR: \
590
CHECK_b1; \
591
SETVALUE(b1 - a0 + TabEnt->Param); \
592
if (pb >= sp->refruns + sp->nruns) \
593
{ \
594
TIFFErrorExtR(tif, module, \
595
"Buffer overflow at line %u of %s %u", \
596
sp->line, \
597
isTiled(tif) ? "tile" : "strip", \
598
isTiled(tif) ? tif->tif_curtile \
599
: tif->tif_curstrip); \
600
return (-1); \
601
} \
602
b1 += *pb++; \
603
break; \
604
case S_VL: \
605
CHECK_b1; \
606
if (b1 < (int)(a0 + TabEnt->Param)) \
607
{ \
608
unexpected("VL", a0); \
609
goto eol2d; \
610
} \
611
SETVALUE(b1 - a0 - TabEnt->Param); \
612
b1 -= *--pb; \
613
break; \
614
case S_Ext: \
615
*pa++ = lastx - a0; \
616
extension(a0); \
617
goto eol2d; \
618
case S_EOL: \
619
*pa++ = lastx - a0; \
620
NeedBits8(4, eof2d); \
621
if (GetBits(4)) \
622
unexpected("EOL", a0); \
623
ClrBits(4); \
624
EOLcnt = 1; \
625
goto eol2d; \
626
default: \
627
badMain2d: \
628
unexpected("MainTable", a0); \
629
goto eol2d; \
630
badBlack2d: \
631
unexpected("BlackTable", a0); \
632
goto eol2d; \
633
badWhite2d: \
634
unexpected("WhiteTable", a0); \
635
goto eol2d; \
636
eof2d: \
637
prematureEOF(a0); \
638
CLEANUP_RUNS(); \
639
goto eoflab; \
640
} \
641
} \
642
if (RunLength) \
643
{ \
644
if (RunLength + a0 < lastx) \
645
{ \
646
/* expect a final V0 */ \
647
NeedBits8(1, eof2d); \
648
if (!GetBits(1)) \
649
goto badMain2d; \
650
ClrBits(1); \
651
} \
652
SETVALUE(0); \
653
} \
654
eol2d: \
655
CLEANUP_RUNS(); \
656
} while (0)
657
#endif /* _FAX3_ */
658
659