Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
tif_fax3.h
Go to the documentation of this file.
1 /* $Id: tif_fax3.h,v 1.5 2005/12/12 09:23:11 dron 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  */
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 typedef 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 */
89 
90 extern const TIFFFaxTabEnt TIFFFaxMainTable[];
91 extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
92 extern 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
179 static 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  } \
366 eof1d: \
367  prematureEOF(a0); \
368  CLEANUP_RUNS(); \
369  goto eoflab; \
370 done1d: \
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  SETVALUE(b1 - a0 - TabEnt->Param); \
482  b1 -= *--pb; \
483  break; \
484  case S_Ext: \
485  *pa++ = lastx - a0; \
486  extension(a0); \
487  goto eol2d; \
488  case S_EOL: \
489  *pa++ = lastx - a0; \
490  NeedBits8(4,eof2d); \
491  if (GetBits(4)) \
492  unexpected("EOL", a0); \
493  ClrBits(4); \
494  EOLcnt = 1; \
495  goto eol2d; \
496  default: \
497  badMain2d: \
498  unexpected("MainTable", a0); \
499  goto eol2d; \
500  badBlack2d: \
501  unexpected("BlackTable", a0); \
502  goto eol2d; \
503  badWhite2d: \
504  unexpected("WhiteTable", a0); \
505  goto eol2d; \
506  eof2d: \
507  prematureEOF(a0); \
508  CLEANUP_RUNS(); \
509  goto eoflab; \
510  } \
511  } \
512  if (RunLength) { \
513  if (RunLength + a0 < lastx) { \
514  /* expect a final V0 */ \
515  NeedBits8(1,eof2d); \
516  if (!GetBits(1)) \
517  goto badMain2d; \
518  ClrBits(1); \
519  } \
520  SETVALUE(0); \
521  } \
522 eol2d: \
523  CLEANUP_RUNS(); \
524 } while (0)
525 #endif /* _FAX3_ */
unsigned char State
Definition: tif_fax3.h:85
const TIFFFaxTabEnt TIFFFaxMainTable[]
Definition: tif_fax3sm.c:5
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
unsigned char Width
Definition: tif_fax3.h:86
uint32 Param
Definition: tif_fax3.h:87
const TIFFFaxTabEnt TIFFFaxBlackTable[]
Definition: tif_fax3sm.c:432
unsigned long uint32
Definition: md5.h:41
void _TIFFFax3fillruns(unsigned char *, uint32 *, uint32 *, uint32)
Definition: tif_fax3.c:364
void(* TIFFFaxFillFunc)(unsigned char *, uint32 *, uint32 *, uint32)
Definition: tif_fax3.h:55
const TIFFFaxTabEnt TIFFFaxWhiteTable[]
Definition: tif_fax3sm.c:20