📄 tif_fax3.c
字号:
/* $Header: /cvsroot/osrs/libtiff/libtiff/tif_fax3.c,v 1.15 2001/09/09 16:10:37 warmerda Exp $ *//* * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 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. */#include "tiffiop.h"#ifdef CCITT_SUPPORT/* * TIFF Library. * * CCITT Group 3 (T.4) and Group 4 (T.6) Compression Support. * * This file contains support for decoding and encoding TIFF * compression algorithms 2, 3, 4, and 32771. * * Decoder support is derived, with permission, from the code * in Frank Cringle's viewfax program; * Copyright (C) 1990, 1995 Frank D. Cringle. */#include "tif_fax3.h"#define G3CODES#include "t4.h"#include <assert.h>#include <stdio.h>/* * Compression+decompression state blocks are * derived from this ``base state'' block. */typedef struct { int rw_mode; /* O_RDONLY for decode, else encode */ int mode; /* operating mode */ uint32 rowbytes; /* bytes in a decoded scanline */ uint32 rowpixels; /* pixels in a scanline */ uint16 cleanfaxdata; /* CleanFaxData tag */ uint32 badfaxrun; /* BadFaxRun tag */ uint32 badfaxlines; /* BadFaxLines tag */ uint32 groupoptions; /* Group 3/4 options tag */ uint32 recvparams; /* encoded Class 2 session params */ char* subaddress; /* subaddress string */ uint32 recvtime; /* time spent receiving (secs) */ TIFFVGetMethod vgetparent; /* super-class method */ TIFFVSetMethod vsetparent; /* super-class method */} Fax3BaseState;#define Fax3State(tif) ((Fax3BaseState*) (tif)->tif_data)typedef struct { Fax3BaseState b; const u_char* bitmap; /* bit reversal table */ uint32 data; /* current i/o byte/word */ int bit; /* current i/o bit in byte */ int EOLcnt; /* count of EOL codes recognized */ TIFFFaxFillFunc fill; /* fill routine */ uint32* runs; /* b&w runs for current/previous row */ uint32* refruns; /* runs for reference line */ uint32* curruns; /* runs for current line */} Fax3DecodeState;#define DecoderState(tif) ((Fax3DecodeState*) Fax3State(tif))typedef enum { G3_1D, G3_2D } Ttag;typedef struct { Fax3BaseState b; int data; /* current i/o byte */ int bit; /* current i/o bit in byte */ Ttag tag; /* encoding state */ u_char* refline; /* reference line for 2d decoding */ int k; /* #rows left that can be 2d encoded */ int maxk; /* max #rows that can be 2d encoded */} Fax3EncodeState;#define EncoderState(tif) ((Fax3EncodeState*) Fax3State(tif))#define is2DEncoding(sp) \ (sp->b.groupoptions & GROUP3OPT_2DENCODING)#define isAligned(p,t) ((((u_long)(p)) & (sizeof (t)-1)) == 0)/* * Group 3 and Group 4 Decoding. *//* * These macros glue the TIFF library state to * the state expected by Frank's decoder. */#define DECLARE_STATE(tif, sp, mod) \ static const char module[] = mod; \ Fax3DecodeState* sp = DecoderState(tif); \ int a0; /* reference element */ \ int lastx = sp->b.rowpixels; /* last element in row */ \ uint32 BitAcc; /* bit accumulator */ \ int BitsAvail; /* # valid bits in BitAcc */ \ int RunLength; /* length of current run */ \ u_char* cp; /* next byte of input data */ \ u_char* ep; /* end of input data */ \ uint32* pa; /* place to stuff next run */ \ uint32* thisrun; /* current row's run array */ \ int EOLcnt; /* # EOL codes recognized */ \ const u_char* bitmap = sp->bitmap; /* input data bit reverser */ \ const TIFFFaxTabEnt* TabEnt#define DECLARE_STATE_2D(tif, sp, mod) \ DECLARE_STATE(tif, sp, mod); \ int b1; /* next change on prev line */ \ uint32* pb /* next run in reference line */\/* * Load any state that may be changed during decoding. */#define CACHE_STATE(tif, sp) do { \ BitAcc = sp->data; \ BitsAvail = sp->bit; \ EOLcnt = sp->EOLcnt; \ cp = (unsigned char*) tif->tif_rawcp; \ ep = cp + tif->tif_rawcc; \} while (0)/* * Save state possibly changed during decoding. */#define UNCACHE_STATE(tif, sp) do { \ sp->bit = BitsAvail; \ sp->data = BitAcc; \ sp->EOLcnt = EOLcnt; \ tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp; \ tif->tif_rawcp = (tidata_t) cp; \} while (0)/* * Setup state for decoding a strip. */static intFax3PreDecode(TIFF* tif, tsample_t s){ Fax3DecodeState* sp = DecoderState(tif); (void) s; assert(sp != NULL); sp->bit = 0; /* force initial read */ sp->data = 0; sp->EOLcnt = 0; /* force initial scan for EOL */ /* * Decoder assumes lsb-to-msb bit order. Note that we select * this here rather than in Fax3SetupState so that viewers can * hold the image open, fiddle with the FillOrder tag value, * and then re-decode the image. Otherwise they'd need to close * and open the image to get the state reset. */ sp->bitmap = TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB); if (sp->refruns) { /* init reference line to white */ sp->refruns[0] = (uint32) sp->b.rowpixels; sp->refruns[1] = 0; } return (1);}/* * Routine for handling various errors/conditions. * Note how they are "glued into the decoder" by * overriding the definitions used by the decoder. */static voidFax3Unexpected(const char* module, TIFF* tif, uint32 a0){ TIFFError(module, "%s: Bad code word at scanline %d (x %lu)", tif->tif_name, tif->tif_row, (u_long) a0);}#define unexpected(table, a0) Fax3Unexpected(module, tif, a0)static voidFax3Extension(const char* module, TIFF* tif, uint32 a0){ TIFFError(module, "%s: Uncompressed data (not supported) at scanline %d (x %lu)", tif->tif_name, tif->tif_row, (u_long) a0);}#define extension(a0) Fax3Extension(module, tif, a0)static voidFax3BadLength(const char* module, TIFF* tif, uint32 a0, uint32 lastx){ TIFFWarning(module, "%s: %s at scanline %d (got %lu, expected %lu)", tif->tif_name, a0 < lastx ? "Premature EOL" : "Line length mismatch", tif->tif_row, (u_long) a0, (u_long) lastx);}#define badlength(a0,lastx) Fax3BadLength(module, tif, a0, lastx)static voidFax3PrematureEOF(const char* module, TIFF* tif, uint32 a0){ TIFFWarning(module, "%s: Premature EOF at scanline %d (x %lu)", tif->tif_name, tif->tif_row, (u_long) a0);}#define prematureEOF(a0) Fax3PrematureEOF(module, tif, a0)#define Nop/* * Decode the requested amount of G3 1D-encoded data. */static intFax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s){ DECLARE_STATE(tif, sp, "Fax3Decode1D"); (void) s; CACHE_STATE(tif, sp); thisrun = sp->curruns; while ((long)occ > 0) { a0 = 0; RunLength = 0; pa = thisrun;#ifdef FAX3_DEBUG printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); printf("-------------------- %d\n", tif->tif_row); fflush(stdout);#endif SYNC_EOL(EOF1D); EXPAND1D(EOF1Da); (*sp->fill)(buf, thisrun, pa, lastx); buf += sp->b.rowbytes; occ -= sp->b.rowbytes; if (occ != 0) tif->tif_row++; continue; EOF1D: /* premature EOF */ CLEANUP_RUNS(); EOF1Da: /* premature EOF */ (*sp->fill)(buf, thisrun, pa, lastx); UNCACHE_STATE(tif, sp); return (-1); } UNCACHE_STATE(tif, sp); return (1);}#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; }/* * Decode the requested amount of G3 2D-encoded data. */static intFax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s){ DECLARE_STATE_2D(tif, sp, "Fax3Decode2D"); int is1D; /* current line is 1d/2d-encoded */ (void) s; CACHE_STATE(tif, sp); while ((long)occ > 0) { a0 = 0; RunLength = 0; pa = thisrun = sp->curruns;#ifdef FAX3_DEBUG printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d", BitAcc, BitsAvail, EOLcnt);#endif SYNC_EOL(EOF2D); NeedBits8(1, EOF2D); is1D = GetBits(1); /* 1D/2D-encoding tag bit */ ClrBits(1);#ifdef FAX3_DEBUG printf(" %s\n-------------------- %d\n", is1D ? "1D" : "2D", tif->tif_row); fflush(stdout);#endif pb = sp->refruns; b1 = *pb++; if (is1D) EXPAND1D(EOF2Da); else EXPAND2D(EOF2Da); (*sp->fill)(buf, thisrun, pa, lastx); SETVAL(0); /* imaginary change for reference */ SWAP(uint32*, sp->curruns, sp->refruns); buf += sp->b.rowbytes; occ -= sp->b.rowbytes; if (occ != 0) tif->tif_row++; continue; EOF2D: /* premature EOF */ CLEANUP_RUNS(); EOF2Da: /* premature EOF */ (*sp->fill)(buf, thisrun, pa, lastx); UNCACHE_STATE(tif, sp); return (-1); } UNCACHE_STATE(tif, sp); return (1);}#undef SWAP/* * The ZERO & FILL macros must handle spans < 2*sizeof(long) bytes. * For machines with 64-bit longs this is <16 bytes; otherwise * this is <8 bytes. We optimize the code here to reflect the * machine characteristics. */#if defined(__alpha) || _MIPS_SZLONG == 64 || defined(__LP64__)#define FILL(n, cp) \ switch (n) { \ case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\ case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\ case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\ case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\ case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ }#define ZERO(n, cp) \ switch (n) { \ case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \ case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \ case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \ case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \ case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ }#else#define FILL(n, cp) \ switch (n) { \ case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \ case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ }#define ZERO(n, cp) \ switch (n) { \ case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \ case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ }#endif/* * Bit-fill a row according to the white/black * runs generated during G3/G4 decoding. */void_TIFFFax3fillruns(u_char* buf, uint32* runs, uint32* erun, uint32 lastx){ static const unsigned char _fillmasks[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; u_char* cp; uint32 x, bx, run; int32 n, nw; long* lp; if ((erun-runs)&1) *erun++ = 0; x = 0; for (; runs < erun; runs += 2) { run = runs[0]; if (x+run > lastx || run > lastx ) run = runs[0] = (uint32) (lastx - x); if (run) { cp = buf + (x>>3); bx = x&7; if (run > 8-bx) { if (bx) { /* align to byte boundary */ *cp++ &= 0xff << (8-bx); run -= 8-bx; } if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */ if ((n/sizeof (long)) > 1) { /* * Align to longword boundary and fill. */ for (; n && !isAligned(cp, long); n--) *cp++ = 0x00; lp = (long*) cp; nw = (int32)(n / sizeof (long)); n -= nw * sizeof (long); do { *lp++ = 0L; } while (--nw); cp = (u_char*) lp; } ZERO(n, cp); run &= 7; } if (run) cp[0] &= 0xff >> run; } else cp[0] &= ~(_fillmasks[run]>>bx); x += runs[0]; } run = runs[1]; if (x+run > lastx || run > lastx ) run = runs[1] = lastx - x; if (run) { cp = buf + (x>>3); bx = x&7; if (run > 8-bx) { if (bx) { /* align to byte boundary */ *cp++ |= 0xff >> bx; run -= 8-bx; } if( (n = run>>3) != 0 ) { /* multiple bytes to fill */ if ((n/sizeof (long)) > 1) { /* * Align to longword boundary and fill. */ for (; n && !isAligned(cp, long); n--) *cp++ = 0xff; lp = (long*) cp; nw = (int32)(n / sizeof (long)); n -= nw * sizeof (long); do { *lp++ = -1L; } while (--nw); cp = (u_char*) lp; } FILL(n, cp); run &= 7; } if (run) cp[0] |= 0xff00 >> run; } else cp[0] |= _fillmasks[run]>>bx; x += runs[1]; } } assert(x == lastx);}#undef ZERO#undef FILL/* * Setup G3/G4-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 decoding or encoding is being done and whether * 1D- or 2D-encoded data is involved. */static intFax3SetupState(TIFF* tif){ TIFFDirectory* td = &tif->tif_dir; Fax3BaseState* sp = Fax3State(tif); long rowbytes, rowpixels; int needsRefLine; 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 = td->td_tilewidth; } else { rowbytes = TIFFScanlineSize(tif); rowpixels = td->td_imagewidth; } sp->rowbytes = (uint32) rowbytes; sp->rowpixels = (uint32) rowpixels; /* * Allocate any additional space required for decoding/encoding. */ needsRefLine = ( (sp->groupoptions & GROUP3OPT_2DENCODING) || td->td_compression == COMPRESSION_CCITTFAX4 ); if (sp->rw_mode == O_RDONLY) { /* 1d/2d decoding */ Fax3DecodeState* dsp = DecoderState(tif); uint32 nruns = needsRefLine ? 2*TIFFroundup(rowpixels,32) : rowpixels; dsp->runs = (uint32*) _TIFFmalloc((2*nruns+3)*sizeof (uint32)); if (dsp->runs == NULL) { TIFFError("Fax3SetupState", "%s: No space for Group 3/4 run arrays", tif->tif_name); return (0); } dsp->curruns = dsp->runs; if (needsRefLine) dsp->refruns = dsp->runs + (nruns>>1); else dsp->refruns = NULL; if (is2DEncoding(dsp)) { /* NB: default is 1D routine */ tif->tif_decoderow = Fax3Decode2D; tif->tif_decodestrip = Fax3Decode2D; tif->tif_decodetile = Fax3Decode2D; } } else if (needsRefLine) { /* 2d encoding */ Fax3EncodeState* esp = EncoderState(tif); /* * 2d encoding requires a scanline * buffer for the ``reference line''; the * scanline against which delta encoding * is referenced. The reference line must
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -