| #ifndef lint |
| static char rcsid[] = "$Header: /cvs/bao-parsec/ext/splash2x/apps/volrend/src/libtiff/tif_fax3.c,v 1.1.1.1 2012/03/29 17:22:43 uid42307 Exp $"; |
| #endif |
| |
| /* |
| * Copyright (c) 1990, 1991, 1992 Sam Leffler |
| * Copyright (c) 1991, 1992 Silicon Graphics, Inc. |
| * |
| * 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. |
| */ |
| |
| /* |
| * TIFF Library. |
| * |
| * CCITT Group 3 and Group 4 Compression Support. |
| */ |
| #include "tiffioP.h" |
| #include <stdio.h> |
| #include <assert.h> |
| #include "tif_fax3.h" |
| #define G3CODES |
| #include "t4.h" |
| #define G3STATES |
| #include "g3states.h" |
| |
| typedef struct { |
| Fax3BaseState b; |
| } Fax3DecodeState; |
| |
| typedef struct { |
| Fax3BaseState b; |
| u_char *wruns; |
| u_char *bruns; |
| short k; /* #rows left that can be 2d encoded */ |
| short maxk; /* max #rows that can be 2d encoded */ |
| } Fax3EncodeState; |
| |
| #if USE_PROTOTYPES |
| static Fax3PreDecode(TIFF *); |
| static Fax3Decode(TIFF*, u_char *, int, u_int); |
| static int Fax3Decode1DRow(TIFF*, u_char *, int); |
| static Fax3PreEncode(TIFF *); |
| static Fax3PostEncode(TIFF *); |
| static Fax3Encode(TIFF*, u_char *, int, u_int); |
| static int Fax3Encode1DRow(TIFF *, u_char *, int); |
| static Fax3Close(TIFF *); |
| static Fax3Cleanup(TIFF *); |
| static void *Fax3SetupState(TIFF *, int); |
| static void fillspan(char *, int, int); |
| static int findspan(u_char **, int, int, u_char const *); |
| static int finddiff(u_char *, int, int, int); |
| static void skiptoeol(TIFF *, int); |
| static void putbits(TIFF *, u_int, u_int); |
| static void putcode(TIFF *, tableentry const *); |
| static void putspan(TIFF *, int, tableentry const *); |
| extern int TIFFFlushData1(TIFF *); |
| #else |
| static int Fax3PreEncode(), Fax3Encode(), Fax3PostEncode(); |
| static int Fax3Encode1DRow(); |
| static int Fax3Decode(), Fax3PreDecode(); |
| static int Fax3Decode1DRow(); |
| static int Fax3Close(), Fax3Cleanup(); |
| static void *Fax3SetupState(); |
| static void fillspan(); |
| static int findspan(); |
| static int finddiff(); |
| static void skiptoeol(); |
| static void putbits(); |
| static void putcode(); |
| static void putspan(); |
| extern int TIFFFlushData1(); |
| #endif |
| |
| TIFFInitCCITTFax3(tif) |
| TIFF *tif; |
| { |
| tif->tif_predecode = Fax3PreDecode; |
| tif->tif_decoderow = Fax3Decode; |
| tif->tif_decodestrip = Fax3Decode; |
| tif->tif_decodetile = Fax3Decode; |
| tif->tif_preencode = Fax3PreEncode; |
| tif->tif_postencode = Fax3PostEncode; |
| tif->tif_encoderow = Fax3Encode; |
| tif->tif_encodestrip = Fax3Encode; |
| tif->tif_encodetile = Fax3Encode; |
| tif->tif_close = Fax3Close; |
| tif->tif_cleanup = Fax3Cleanup; |
| tif->tif_options |= FAX3_CLASSF; /* default */ |
| tif->tif_flags |= TIFF_NOBITREV; /* we handle bit reversal */ |
| return (1); |
| } |
| |
| TIFFModeCCITTFax3(tif, isClassF) |
| TIFF *tif; |
| int isClassF; |
| { |
| if (isClassF) |
| tif->tif_options |= FAX3_CLASSF; |
| else |
| tif->tif_options &= ~FAX3_CLASSF; |
| } |
| |
| static u_char bitMask[8] = |
| { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; |
| #define isBitSet(sp) ((sp)->b.data & bitMask[(sp)->b.bit]) |
| |
| #define is2DEncoding(tif) \ |
| (tif->tif_dir.td_group3options & GROUP3OPT_2DENCODING) |
| #define fetchByte(tif, sp) \ |
| ((tif)->tif_rawcc--, (sp)->b.bitmap[*(u_char *)(tif)->tif_rawcp++]) |
| |
| #define BITCASE(b) \ |
| case b: \ |
| code <<= 1; \ |
| if (data & (1<<(7-b))) code |= 1;\ |
| len++; \ |
| if (code > 0) { bit = b+1; break; } |
| |
| /* |
| * Skip over input until an EOL code is found. The |
| * value of len is passed as 0 except during error |
| * recovery when decoding 2D data. Note also that |
| * we don't use the optimized state tables to locate |
| * an EOL because we can't assume much of anything |
| * about our state (e.g. bit position). |
| */ |
| static void |
| skiptoeol(tif, len) |
| TIFF *tif; |
| int len; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| register int bit = sp->b.bit; |
| register int data = sp->b.data; |
| int code = 0; |
| |
| /* |
| * Our handling of ``bit'' is painful because |
| * the rest of the code does not maintain it as |
| * exactly the bit offset in the current data |
| * byte (bit == 0 means refill the data byte). |
| * Thus we have to be careful on entry and |
| * exit to insure that we maintain a value that's |
| * understandable elsewhere in the decoding logic. |
| */ |
| if (bit == 0) /* force refill */ |
| bit = 8; |
| for (;;) { |
| switch (bit) { |
| again: BITCASE(0); |
| BITCASE(1); |
| BITCASE(2); |
| BITCASE(3); |
| BITCASE(4); |
| BITCASE(5); |
| BITCASE(6); |
| BITCASE(7); |
| default: |
| if (tif->tif_rawcc <= 0) |
| return; |
| data = fetchByte(tif, sp); |
| goto again; |
| } |
| if (len >= 12 && code == EOL) |
| break; |
| code = len = 0; |
| } |
| sp->b.bit = bit > 7 ? 0 : bit; /* force refill */ |
| sp->b.data = data; |
| } |
| |
| /* |
| * Return the next bit in the input stream. This is |
| * used to extract 2D tag values and the color tag |
| * at the end of a terminating uncompressed data code. |
| */ |
| static int |
| nextbit(tif) |
| TIFF *tif; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| int bit; |
| |
| if (sp->b.bit == 0 && tif->tif_rawcc > 0) |
| sp->b.data = fetchByte(tif, sp); |
| bit = isBitSet(sp); |
| if (++(sp->b.bit) > 7) |
| sp->b.bit = 0; |
| return (bit); |
| } |
| |
| static void |
| bset(cp, n, v) |
| register unsigned char *cp; |
| register int n; |
| register int v; |
| { |
| while (n-- > 0) |
| *cp++ = v; |
| } |
| |
| /* |
| * Setup G3-related compression/decompression |
| * state before data is processed. This routine |
| * is called once per image -- it sets up different |
| * state based on whether or not 2D encoding is used. |
| */ |
| static void * |
| Fax3SetupState(tif, space) |
| TIFF *tif; |
| int space; |
| { |
| TIFFDirectory *td = &tif->tif_dir; |
| Fax3BaseState *sp; |
| int cc = space; |
| long rowbytes, rowpixels; |
| |
| if (td->td_bitspersample != 1) { |
| TIFFError(tif->tif_name, |
| "Bits/sample must be 1 for Group 3/4 encoding/decoding"); |
| return (0); |
| } |
| /* |
| * Calculate the scanline/tile widths. |
| */ |
| if (isTiled(tif)) { |
| rowbytes = TIFFTileRowSize(tif); |
| rowpixels = tif->tif_dir.td_tilewidth; |
| } else { |
| rowbytes = TIFFScanlineSize(tif); |
| rowpixels = tif->tif_dir.td_imagewidth; |
| } |
| if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4) |
| cc += rowbytes+1; |
| tif->tif_data = malloc(cc); |
| if (tif->tif_data == NULL) { |
| TIFFError("Fax3SetupState", |
| "%s: No space for Fax3 state block", tif->tif_name); |
| return (0); |
| } |
| sp = (Fax3BaseState *)tif->tif_data; |
| sp->rowbytes = rowbytes; |
| sp->rowpixels = rowpixels; |
| sp->bitmap = (tif->tif_fillorder != td->td_fillorder ? |
| TIFFBitRevTable : TIFFNoBitRevTable); |
| sp->white = (td->td_photometric == PHOTOMETRIC_MINISBLACK); |
| if (is2DEncoding(tif) || td->td_compression == COMPRESSION_CCITTFAX4) { |
| /* |
| * 2d encoding/decoding requires a scanline |
| * buffer for the ``reference line''; the |
| * scanline against which delta encoding |
| * is referenced. The reference line must |
| * be initialized to be ``white'' (done elsewhere). |
| */ |
| sp->refline = (u_char *)tif->tif_data + space + 1; |
| /* |
| * Initialize pixel just to the left of the |
| * reference line to white. This extra pixel |
| * simplifies the edge-condition logic. |
| */ |
| sp->refline[-1] = sp->white ? 0xff : 0x00; |
| } else |
| sp->refline = 0; |
| return (sp); |
| } |
| |
| /* |
| * Setup state for decoding a strip. |
| */ |
| static |
| Fax3PreDecode(tif) |
| TIFF *tif; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| |
| if (sp == NULL) { |
| sp = (Fax3DecodeState *)Fax3SetupState(tif, sizeof (*sp)); |
| if (!sp) |
| return (0); |
| } |
| sp->b.bit = 0; /* force initial read */ |
| sp->b.data = 0; |
| sp->b.tag = G3_1D; |
| if (sp->b.refline) |
| bset(sp->b.refline, sp->b.rowbytes, sp->b.white ? 0xff : 0x00); |
| /* |
| * If image has EOL codes, they precede each line |
| * of data. We skip over the first one here so that |
| * when we decode rows, we can use an EOL to signal |
| * that less than the expected number of pixels are |
| * present for the scanline. |
| */ |
| if ((tif->tif_options & FAX3_NOEOL) == 0) { |
| skiptoeol(tif, 0); |
| if (is2DEncoding(tif)) |
| /* tag should always be 1D! */ |
| sp->b.tag = nextbit(tif) ? G3_1D : G3_2D; |
| } |
| return (1); |
| } |
| |
| /* |
| * Fill a span with ones. |
| */ |
| static void |
| fillspan(cp, x, count) |
| register char *cp; |
| register int x, count; |
| { |
| static const unsigned char masks[] = |
| { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; |
| |
| if (count <= 0) |
| return; |
| cp += x>>3; |
| if (x &= 7) { /* align to byte boundary */ |
| if (count < 8 - x) { |
| *cp++ |= masks[count] >> x; |
| return; |
| } |
| *cp++ |= 0xff >> x; |
| count -= 8 - x; |
| } |
| while (count >= 8) { |
| *cp++ = 0xff; |
| count -= 8; |
| } |
| *cp |= masks[count]; |
| } |
| |
| /* |
| * Decode the requested amount of data. |
| */ |
| static |
| Fax3Decode(tif, buf, occ, s) |
| TIFF *tif; |
| u_char *buf; |
| int occ; |
| u_int s; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| |
| bzero(buf, occ); /* decoding only sets non-zero bits */ |
| while (occ > 0) { |
| if (sp->b.tag == G3_1D) { |
| if (!Fax3Decode1DRow(tif, buf, sp->b.rowpixels)) |
| return (0); |
| } else { |
| if (!Fax3Decode2DRow(tif, buf, sp->b.rowpixels)) |
| return (0); |
| } |
| if (is2DEncoding(tif)) { |
| /* |
| * Fetch the tag bit that indicates |
| * whether the next row is 1d or 2d |
| * encoded. If 2d-encoded, then setup |
| * the reference line from the decoded |
| * scanline just completed. |
| */ |
| sp->b.tag = nextbit(tif) ? G3_1D : G3_2D; |
| if (sp->b.tag == G3_2D) |
| bcopy(buf, sp->b.refline, sp->b.rowbytes); |
| } |
| buf += sp->b.rowbytes; |
| occ -= sp->b.rowbytes; |
| } |
| return (1); |
| } |
| |
| /* |
| * Decode a run of white. |
| */ |
| static int |
| decode_white_run(tif) |
| TIFF *tif; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| short state = sp->b.bit; |
| short action; |
| int runlen = 0; |
| |
| for (;;) { |
| if (sp->b.bit == 0) { |
| nextbyte: |
| if (tif->tif_rawcc <= 0) |
| return (G3CODE_EOF); |
| sp->b.data = fetchByte(tif, sp); |
| } |
| action = TIFFFax1DAction[state][sp->b.data]; |
| state = TIFFFax1DNextState[state][sp->b.data]; |
| if (action == ACT_INCOMP) |
| goto nextbyte; |
| if (action == ACT_INVALID) |
| return (G3CODE_INVALID); |
| if (action == ACT_EOL) |
| return (G3CODE_EOL); |
| sp->b.bit = state; |
| action = RUNLENGTH(action - ACT_WRUNT); |
| runlen += action; |
| if (action < 64) |
| return (runlen); |
| } |
| /*NOTREACHED*/ |
| } |
| |
| /* |
| * Decode a run of black. |
| */ |
| static int |
| decode_black_run(tif) |
| TIFF *tif; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| short state = sp->b.bit + 8; |
| short action; |
| int runlen = 0; |
| |
| for (;;) { |
| if (sp->b.bit == 0) { |
| nextbyte: |
| if (tif->tif_rawcc <= 0) |
| return (G3CODE_EOF); |
| sp->b.data = fetchByte(tif, sp); |
| } |
| action = TIFFFax1DAction[state][sp->b.data]; |
| state = TIFFFax1DNextState[state][sp->b.data]; |
| if (action == ACT_INCOMP) |
| goto nextbyte; |
| if (action == ACT_INVALID) |
| return (G3CODE_INVALID); |
| if (action == ACT_EOL) |
| return (G3CODE_EOL); |
| sp->b.bit = state; |
| action = RUNLENGTH(action - ACT_BRUNT); |
| runlen += action; |
| if (action < 64) |
| return (runlen); |
| state += 8; |
| } |
| /*NOTREACHED*/ |
| } |
| |
| /* |
| * Process one row of 1d Huffman-encoded data. |
| */ |
| static int |
| Fax3Decode1DRow(tif, buf, npels) |
| TIFF *tif; |
| u_char *buf; |
| int npels; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| int x = 0; |
| int runlen; |
| short action; |
| short color = sp->b.white; |
| static char module[] = "Fax3Decode1D"; |
| |
| for (;;) { |
| if (color == sp->b.white) |
| runlen = decode_white_run(tif); |
| else |
| runlen = decode_black_run(tif); |
| switch (runlen) { |
| case G3CODE_EOF: |
| TIFFError(module, |
| "%s: Premature EOF at scanline %d (x %d)", |
| tif->tif_name, tif->tif_row, x); |
| return (0); |
| case G3CODE_INVALID: /* invalid code */ |
| /* |
| * An invalid code was encountered. |
| * Flush the remainder of the line |
| * and allow the caller to decide whether |
| * or not to continue. Note that this |
| * only works if we have a G3 image |
| * with EOL markers. |
| */ |
| TIFFError(module, |
| "%s: Bad code word at scanline %d (x %d)", |
| tif->tif_name, tif->tif_row, x); |
| goto done; |
| case G3CODE_EOL: /* premature end-of-line code */ |
| TIFFWarning(module, |
| "%s: Premature EOL at scanline %d (x %d)", |
| tif->tif_name, tif->tif_row, x); |
| return (1); /* try to resynchronize... */ |
| } |
| if (x+runlen > npels) |
| runlen = npels-x; |
| if (runlen > 0) { |
| if (color) |
| fillspan((char *)buf, x, runlen); |
| x += runlen; |
| if (x >= npels) |
| break; |
| } |
| color = !color; |
| } |
| done: |
| /* |
| * Cleanup at the end of the row. This convoluted |
| * logic is merely so that we can reuse the code with |
| * two other related compression algorithms (2 & 32771). |
| * |
| * Note also that our handling of word alignment assumes |
| * that the buffer is at least word aligned. This is |
| * the case for most all versions of malloc (typically |
| * the buffer is returned longword aligned). |
| */ |
| if ((tif->tif_options & FAX3_NOEOL) == 0) |
| skiptoeol(tif, 0); |
| if (tif->tif_options & FAX3_BYTEALIGN) |
| sp->b.bit = 0; |
| if ((tif->tif_options & FAX3_WORDALIGN) && ((long)tif->tif_rawcp & 1)) |
| (void) fetchByte(tif, sp); |
| return (x == npels); |
| } |
| |
| /* |
| * Group 3 2d Decoding support. |
| */ |
| |
| /* |
| * Return the next uncompressed mode code word. |
| */ |
| static int |
| decode_uncomp_code(tif) |
| TIFF *tif; |
| { |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| short code; |
| |
| do { |
| if (sp->b.bit == 0 || sp->b.bit > 7) { |
| if (tif->tif_rawcc <= 0) |
| return (UNCOMP_EOF); |
| sp->b.data = fetchByte(tif, sp); |
| } |
| code = TIFFFaxUncompAction[sp->b.bit][sp->b.data]; |
| sp->b.bit = TIFFFaxUncompNextState[sp->b.bit][sp->b.data]; |
| } while (code == ACT_INCOMP); |
| return (code); |
| } |
| |
| /* |
| * Process one row of 2d encoded data. |
| */ |
| int |
| Fax3Decode2DRow(tif, buf, npels) |
| TIFF *tif; |
| u_char *buf; |
| int npels; |
| { |
| #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) |
| Fax3DecodeState *sp = (Fax3DecodeState *)tif->tif_data; |
| int a0 = -1; |
| int b1, b2; |
| int run1, run2; /* for horizontal mode */ |
| short mode; |
| short color = sp->b.white; |
| static char module[] = "Fax3Decode2D"; |
| |
| do { |
| if (sp->b.bit == 0 || sp->b.bit > 7) { |
| if (tif->tif_rawcc <= 0) { |
| TIFFError(module, |
| "%s: Premature EOF at scanline %d", |
| tif->tif_name, tif->tif_row); |
| return (0); |
| } |
| sp->b.data = fetchByte(tif, sp); |
| } |
| mode = TIFFFax2DMode[sp->b.bit][sp->b.data]; |
| sp->b.bit = TIFFFax2DNextState[sp->b.bit][sp->b.data]; |
| switch (mode) { |
| case MODE_NULL: |
| break; |
| case MODE_PASS: |
| b2 = finddiff(sp->b.refline, a0, npels, !color); |
| b1 = finddiff(sp->b.refline, b2, npels, color); |
| b2 = finddiff(sp->b.refline, b1, npels, !color); |
| if (color) { |
| if (a0 < 0) |
| a0 = 0; |
| fillspan((char *)buf, a0, b2 - a0); |
| } |
| a0 = b2; |
| break; |
| case MODE_HORIZ: |
| if (color == sp->b.white) { |
| run1 = decode_white_run(tif); |
| run2 = decode_black_run(tif); |
| } else { |
| run1 = decode_black_run(tif); |
| run2 = decode_white_run(tif); |
| } |
| /* |
| * Do the appropriate fill. Note that we exit |
| * this logic with the same color that we enter |
| * with since we do 2 fills. This explains the |
| * somewhat obscure logic below. |
| */ |
| if (a0 < 0) |
| a0 = 0; |
| if (a0 + run1 > npels) |
| run1 = npels - a0; |
| if (color) |
| fillspan((char *)buf, a0, run1); |
| a0 += run1; |
| if (a0 + run2 > npels) |
| run2 = npels - a0; |
| if (!color) |
| fillspan((char *)buf, a0, run2); |
| a0 += run2; |
| break; |
| case MODE_VERT_V0: |
| case MODE_VERT_VR1: |
| case MODE_VERT_VR2: |
| case MODE_VERT_VR3: |
| case MODE_VERT_VL1: |
| case MODE_VERT_VL2: |
| case MODE_VERT_VL3: |
| b2 = finddiff(sp->b.refline, a0, npels, !color); |
| b1 = finddiff(sp->b.refline, b2, npels, color); |
| b1 += mode - MODE_VERT_V0; |
| if (color) { |
| if (a0 < 0) |
| a0 = 0; |
| fillspan((char *)buf, a0, b1 - a0); |
| } |
| color = !color; |
| a0 = b1; |
| break; |
| case MODE_UNCOMP: |
| /* |
| * Uncompressed mode: select from the |
| * special set of code words. |
| */ |
| if (a0 < 0) |
| a0 = 0; |
| do { |
| mode = decode_uncomp_code(tif); |
| switch (mode) { |
| case UNCOMP_RUN1: |
| case UNCOMP_RUN2: |
| case UNCOMP_RUN3: |
| case UNCOMP_RUN4: |
| case UNCOMP_RUN5: |
| run1 = mode - UNCOMP_RUN0; |
| fillspan((char *)buf, a0+run1-1, 1); |
| a0 += run1; |
| break; |
| case UNCOMP_RUN6: |
| a0 += 5; |
| break; |
| case UNCOMP_TRUN0: |
| case UNCOMP_TRUN1: |
| case UNCOMP_TRUN2: |
| case UNCOMP_TRUN3: |
| case UNCOMP_TRUN4: |
| run1 = mode - UNCOMP_TRUN0; |
| a0 += run1; |
| color = nextbit(tif) ? |
| !sp->b.white : sp->b.white; |
| break; |
| case UNCOMP_INVALID: |
| TIFFError(module, |
| "%s: Bad uncompressed code word at scanline %d", |
| tif->tif_name, tif->tif_row); |
| goto bad; |
| case UNCOMP_EOF: |
| TIFFError(module, |
| "%s: Premature EOF at scanline %d", |
| tif->tif_name, tif->tif_row); |
| return (0); |
| } |
| } while (mode < UNCOMP_EXIT); |
| break; |
| case MODE_ERROR_1: |
| if ((tif->tif_options & FAX3_NOEOL) == 0) { |
| TIFFWarning(module, |
| "%s: Premature EOL at scanline %d (x %d)", |
| tif->tif_name, tif->tif_row, a0); |
| skiptoeol(tif, 7); /* seen 7 0's already */ |
| return (1); /* try to synchronize */ |
| } |
| /* fall thru... */ |
| case MODE_ERROR: |
| TIFFError(module, |
| "%s: Bad 2D code word at scanline %d", |
| tif->tif_name, tif->tif_row); |
| goto bad; |
| default: |
| TIFFError(module, |
| "%s: Panic, bad decoding state at scanline %d", |
| tif->tif_name, tif->tif_row); |
| return (0); |
| } |
| } while (a0 < npels); |
| bad: |
| /* |
| * Cleanup at the end of row. We check for |
| * EOL separately so that this code can be |
| * reused by the Group 4 decoding routine. |
| */ |
| if ((tif->tif_options & FAX3_NOEOL) == 0) |
| skiptoeol(tif, 0); |
| return (a0 >= npels); |
| #undef PIXEL |
| } |
| |
| /* |
| * CCITT Group 3 FAX Encoding. |
| */ |
| |
| /* |
| * Write a variable-length bit-value to |
| * the output stream. Values are |
| * assumed to be at most 16 bits. |
| */ |
| static void |
| putbits(tif, bits, length) |
| TIFF *tif; |
| u_int bits, length; |
| { |
| Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; |
| static const int mask[9] = |
| { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; |
| |
| while (length > sp->bit) { |
| sp->data |= bits >> (length - sp->bit); |
| length -= sp->bit; |
| Fax3FlushBits(tif, sp); |
| } |
| sp->data |= (bits & mask[length]) << (sp->bit - length); |
| sp->bit -= length; |
| if (sp->bit == 0) |
| Fax3FlushBits(tif, sp); |
| } |
| |
| /* |
| * Write a code to the output stream. |
| */ |
| static void |
| putcode(tif, te) |
| TIFF *tif; |
| tableentry const *te; |
| { |
| putbits(tif, te->code, te->length); |
| } |
| |
| /* |
| * Write the sequence of codes that describes |
| * the specified span of zero's or one's. The |
| * appropriate table that holds the make-up and |
| * terminating codes is supplied. |
| */ |
| static void |
| putspan(tif, span, tab) |
| TIFF *tif; |
| int span; |
| tableentry const *tab; |
| { |
| while (span >= 2624) { |
| tableentry const *te = &tab[63 + (2560>>6)]; |
| putcode(tif, te); |
| span -= te->runlen; |
| } |
| if (span >= 64) { |
| tableentry const *te = &tab[63 + (span>>6)]; |
| assert(te->runlen == 64*(span>>6)); |
| putcode(tif, te); |
| span -= te->runlen; |
| } |
| putcode(tif, &tab[span]); |
| } |
| |
| /* |
| * Write an EOL code to the output stream. The zero-fill |
| * logic for byte-aligning encoded scanlines is handled |
| * here. We also handle writing the tag bit for the next |
| * scanline when doing 2d encoding. |
| */ |
| void |
| Fax3PutEOL(tif) |
| TIFF *tif; |
| { |
| Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; |
| |
| if (tif->tif_dir.td_group3options & GROUP3OPT_FILLBITS) { |
| /* |
| * Force bit alignment so EOL will terminate on |
| * a byte boundary. That is, force the bit alignment |
| * to 16-12 = 4 before putting out the EOL code. |
| */ |
| int align = 8 - 4; |
| if (align != sp->bit) { |
| if (align > sp->bit) |
| align = sp->bit + (8 - align); |
| else |
| align = sp->bit - align; |
| putbits(tif, 0, align); |
| } |
| } |
| putbits(tif, EOL, 12); |
| if (is2DEncoding(tif)) |
| putbits(tif, sp->tag == G3_1D, 1); |
| } |
| |
| static const u_char zeroruns[256] = { |
| 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ |
| }; |
| static const u_char oneruns[256] = { |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ |
| 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ |
| 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */ |
| }; |
| |
| /* |
| * Reset encoding state at the start of a strip. |
| */ |
| static |
| Fax3PreEncode(tif) |
| TIFF *tif; |
| { |
| Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; |
| |
| if (sp == NULL) { |
| sp = (Fax3EncodeState *)Fax3SetupState(tif, sizeof (*sp)); |
| if (!sp) |
| return (0); |
| if (sp->b.white == 0) { |
| sp->wruns = zeroruns; |
| sp->bruns = oneruns; |
| } else { |
| sp->wruns = oneruns; |
| sp->bruns = zeroruns; |
| } |
| } |
| sp->b.bit = 8; |
| sp->b.data = 0; |
| sp->b.tag = G3_1D; |
| /* |
| * This is necessary for Group 4; otherwise it isn't |
| * needed because the first scanline of each strip ends |
| * up being copied into the refline. |
| */ |
| if (sp->b.refline) |
| bset(sp->b.refline, sp->b.rowbytes, sp->b.white ? 0xff : 0x00); |
| if (is2DEncoding(tif)) { |
| float res = tif->tif_dir.td_yresolution; |
| /* |
| * The CCITT spec says that when doing 2d encoding, you |
| * should only do it on K consecutive scanlines, where K |
| * depends on the resolution of the image being encoded |
| * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory |
| * code initializes td_yresolution to 0, this code will |
| * select a K of 2 unless the YResolution tag is set |
| * appropriately. (Note also that we fudge a little here |
| * and use 150 lpi to avoid problems with units conversion.) |
| */ |
| if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) |
| res = (res * .3937) / 2.54; /* convert to inches */ |
| sp->maxk = (res > 150 ? 4 : 2); |
| sp->k = sp->maxk-1; |
| } else |
| sp->k = sp->maxk = 0; |
| return (1); |
| } |
| |
| /* |
| * 1d-encode a row of pixels. The encoding is |
| * a sequence of all-white or all-black spans |
| * of pixels encoded with Huffman codes. |
| */ |
| static int |
| Fax3Encode1DRow(tif, bp, bits) |
| TIFF *tif; |
| u_char *bp; |
| int bits; |
| { |
| Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; |
| int bs = 0, span; |
| |
| for (;;) { |
| span = findspan(&bp, bs, bits, sp->wruns); /* white span */ |
| putspan(tif, span, TIFFFaxWhiteCodes); |
| bs += span; |
| if (bs >= bits) |
| break; |
| span = findspan(&bp, bs, bits, sp->bruns); /* black span */ |
| putspan(tif, span, TIFFFaxBlackCodes); |
| bs += span; |
| if (bs >= bits) |
| break; |
| } |
| return (1); |
| } |
| |
| static const tableentry horizcode = |
| { 3, 0x1 }; /* 001 */ |
| static const tableentry passcode = |
| { 4, 0x1 }; /* 0001 */ |
| static const tableentry vcodes[7] = { |
| { 7, 0x03 }, /* 0000 011 */ |
| { 6, 0x03 }, /* 0000 11 */ |
| { 3, 0x03 }, /* 011 */ |
| { 1, 0x1 }, /* 1 */ |
| { 3, 0x2 }, /* 010 */ |
| { 6, 0x02 }, /* 0000 10 */ |
| { 7, 0x02 } /* 0000 010 */ |
| }; |
| |
| /* |
| * 2d-encode a row of pixels. Consult the CCITT |
| * documentation for the algorithm. |
| */ |
| int |
| Fax3Encode2DRow(tif, bp, rp, bits) |
| TIFF *tif; |
| u_char *bp, *rp; |
| int bits; |
| { |
| #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) |
| short white = ((Fax3BaseState *)tif->tif_data)->white; |
| int a0 = 0; |
| int a1 = (PIXEL(bp, 0) != white ? 0 : finddiff(bp, 0, bits, white)); |
| int b1 = (PIXEL(rp, 0) != white ? 0 : finddiff(rp, 0, bits, white)); |
| int a2, b2; |
| |
| for (;;) { |
| b2 = finddiff(rp, b1, bits, PIXEL(rp,b1)); |
| if (b2 >= a1) { |
| int d = b1 - a1; |
| if (!(-3 <= d && d <= 3)) { /* horizontal mode */ |
| a2 = finddiff(bp, a1, bits, PIXEL(bp,a1)); |
| putcode(tif, &horizcode); |
| if (a0+a1 == 0 || PIXEL(bp, a0) == white) { |
| putspan(tif, a1-a0, TIFFFaxWhiteCodes); |
| putspan(tif, a2-a1, TIFFFaxBlackCodes); |
| } else { |
| putspan(tif, a1-a0, TIFFFaxBlackCodes); |
| putspan(tif, a2-a1, TIFFFaxWhiteCodes); |
| } |
| a0 = a2; |
| } else { /* vertical mode */ |
| putcode(tif, &vcodes[d+3]); |
| a0 = a1; |
| } |
| } else { /* pass mode */ |
| putcode(tif, &passcode); |
| a0 = b2; |
| } |
| if (a0 >= bits) |
| break; |
| a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); |
| b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); |
| b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); |
| } |
| return (1); |
| #undef PIXEL |
| } |
| |
| /* |
| * Encode a buffer of pixels. |
| */ |
| static int |
| Fax3Encode(tif, bp, cc, s) |
| TIFF *tif; |
| u_char *bp; |
| int cc; |
| u_int s; |
| { |
| Fax3EncodeState *sp = (Fax3EncodeState *)tif->tif_data; |
| |
| while (cc > 0) { |
| Fax3PutEOL(tif); |
| if (is2DEncoding(tif)) { |
| if (sp->b.tag == G3_1D) { |
| if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) |
| return (0); |
| sp->b.tag = G3_2D; |
| } else { |
| if (!Fax3Encode2DRow(tif, bp, sp->b.refline, sp->b.rowpixels)) |
| return (0); |
| sp->k--; |
| } |
| if (sp->k == 0) { |
| sp->b.tag = G3_1D; |
| sp->k = sp->maxk-1; |
| } else |
| bcopy(bp, sp->b.refline, sp->b.rowbytes); |
| } else { |
| if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) |
| return (0); |
| } |
| bp += sp->b.rowbytes; |
| cc -= sp->b.rowbytes; |
| } |
| return (1); |
| } |
| |
| static int |
| Fax3PostEncode(tif) |
| TIFF *tif; |
| { |
| Fax3BaseState *sp = (Fax3BaseState *)tif->tif_data; |
| |
| if (sp->bit != 8) |
| Fax3FlushBits(tif, sp); |
| return (1); |
| } |
| |
| static |
| Fax3Close(tif) |
| TIFF *tif; |
| { |
| if ((tif->tif_options & FAX3_CLASSF) == 0) { /* append RTC */ |
| int i; |
| for (i = 0; i < 6; i++) |
| Fax3PutEOL(tif); |
| (void) Fax3PostEncode(tif); |
| } |
| } |
| |
| static |
| Fax3Cleanup(tif) |
| TIFF *tif; |
| { |
| if (tif->tif_data) { |
| free(tif->tif_data); |
| tif->tif_data = NULL; |
| } |
| } |
| |
| /* |
| * Bit handling utilities. |
| */ |
| |
| /* |
| * Find a span of ones or zeros using the supplied |
| * table. The byte-aligned start of the bit string |
| * is supplied along with the start+end bit indices. |
| * The table gives the number of consecutive ones or |
| * zeros starting from the msb and is indexed by byte |
| * value. |
| */ |
| static int |
| findspan(bpp, bs, be, tab) |
| u_char **bpp; |
| int bs, be; |
| register u_char const *tab; |
| { |
| register u_char *bp = *bpp; |
| register int bits = be - bs; |
| register int n, span; |
| |
| /* |
| * Check partial byte on lhs. |
| */ |
| if (bits > 0 && (n = (bs & 7))) { |
| span = tab[(*bp << n) & 0xff]; |
| if (span > 8-n) /* table value too generous */ |
| span = 8-n; |
| if (span > bits) /* constrain span to bit range */ |
| span = bits; |
| if (n+span < 8) /* doesn't extend to edge of byte */ |
| goto done; |
| bits -= span; |
| bp++; |
| } else |
| span = 0; |
| /* |
| * Scan full bytes for all 1's or all 0's. |
| */ |
| while (bits >= 8) { |
| n = tab[*bp]; |
| span += n; |
| bits -= n; |
| if (n < 8) /* end of run */ |
| goto done; |
| bp++; |
| } |
| /* |
| * Check partial byte on rhs. |
| */ |
| if (bits > 0) { |
| n = tab[*bp]; |
| span += (n > bits ? bits : n); |
| } |
| done: |
| *bpp = bp; |
| return (span); |
| } |
| |
| /* |
| * Return the offset of the next bit in the range |
| * [bs..be] that is different from the specified |
| * color. The end, be, is returned if no such bit |
| * exists. |
| */ |
| static int |
| finddiff(cp, bs, be, color) |
| u_char *cp; |
| int bs, be, color; |
| { |
| cp += bs >> 3; /* adjust byte offset */ |
| return (bs + findspan(&cp, bs, be, color ? oneruns : zeroruns)); |
| } |