tif_lzw.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 746 行 · 第 1/2 页
C
746 行
/* $Header: /pack/cvsroots/wxwidgets/wxWindows/src/tiff/tif_lzw.c,v 1.6 2004/11/19 22:29:44 VZ Exp $ */
/*
* Copyright (c) 1988-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 LZW_SUPPORT
/*
* TIFF Library.
* Rev 5.0 Lempel-Ziv & Welch Compression Support
*
* This code is derived from the compress program whose code is
* derived from software contributed to Berkeley by James A. Woods,
* derived from original work by Spencer Thomas and Joseph Orost.
*
* The original Berkeley copyright notice appears below in its entirety.
*/
#include "tif_predict.h"
#include <assert.h>
#include <stdio.h>
/*
* NB: The 5.0 spec describes a different algorithm than Aldus
* implements. Specifically, Aldus does code length transitions
* one code earlier than should be done (for real LZW).
* Earlier versions of this library implemented the correct
* LZW algorithm, but emitted codes in a bit order opposite
* to the TIFF spec. Thus, to maintain compatibility w/ Aldus
* we interpret MSB-LSB ordered codes to be images written w/
* old versions of this library, but otherwise adhere to the
* Aldus "off by one" algorithm.
*
* Future revisions to the TIFF spec are expected to "clarify this issue".
*/
#define LZW_COMPAT /* include backwards compatibility code */
/*
* Each strip of data is supposed to be terminated by a CODE_EOI.
* If the following #define is included, the decoder will also
* check for end-of-strip w/o seeing this code. This makes the
* library more robust, but also slower.
*/
#define LZW_CHECKEOS /* include checks for strips w/o EOI code */
#define MAXCODE(n) ((1L<<(n))-1)
/*
* The TIFF spec specifies that encoded bit
* strings range from 9 to 12 bits.
*/
#define BITS_MIN 9 /* start with 9 bits */
#define BITS_MAX 12 /* max of 12 bit strings */
/* predefined codes */
#define CODE_CLEAR 256 /* code to clear string table */
#define CODE_EOI 257 /* end-of-information code */
#define CODE_FIRST 258 /* first free code entry */
#define CODE_MAX MAXCODE(BITS_MAX)
#define HSIZE 9001L /* 91% occupancy */
#define HSHIFT (13-8)
#ifdef LZW_COMPAT
/* NB: +1024 is for compatibility with old files */
#define CSIZE (MAXCODE(BITS_MAX)+1024L)
#else
#define CSIZE (MAXCODE(BITS_MAX)+1L)
#endif
/*
* State block for each open TIFF file using LZW
* compression/decompression. Note that the predictor
* state block must be first in this data structure.
*/
typedef struct {
TIFFPredictorState predict; /* predictor super class */
u_short nbits; /* # of bits/code */
u_short maxcode; /* maximum code for lzw_nbits */
u_short free_ent; /* next free entry in hash table */
long nextdata; /* next bits of i/o */
long nextbits; /* # of valid bits in lzw_nextdata */
} LZWBaseState;
#define lzw_nbits base.nbits
#define lzw_maxcode base.maxcode
#define lzw_free_ent base.free_ent
#define lzw_nextdata base.nextdata
#define lzw_nextbits base.nextbits
/*
* Encoding-specific state.
*/
typedef uint16 hcode_t; /* codes fit in 16 bits */
/*
* Decoding-specific state.
*/
typedef struct code_ent {
struct code_ent *next;
u_short length; /* string len, including this token */
u_char value; /* data value */
u_char firstchar; /* first token of string */
} code_t;
typedef int (*decodeFunc)(TIFF*, tidata_t, tsize_t, tsample_t);
typedef struct {
LZWBaseState base;
/* Decoding specific data */
long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */
long dec_restart; /* restart count */
#ifdef LZW_CHECKEOS
long dec_bitsleft; /* available bits in raw data */
#endif
decodeFunc dec_decode; /* regular or backwards compatible */
code_t* dec_codep; /* current recognized code */
code_t* dec_oldcodep; /* previously recognized code */
code_t* dec_free_entp; /* next free entry */
code_t* dec_maxcodep; /* max available entry */
code_t* dec_codetab; /* kept separate for small machines */
} LZWCodecState;
#define LZWState(tif) ((LZWBaseState*) (tif)->tif_data)
#define DecoderState(tif) ((LZWCodecState*) LZWState(tif))
static int LZWDecode(TIFF*, tidata_t, tsize_t, tsample_t);
#ifdef LZW_COMPAT
static int LZWDecodeCompat(TIFF*, tidata_t, tsize_t, tsample_t);
#endif
/*
* LZW Decoder.
*/
#ifdef LZW_CHECKEOS
/*
* This check shouldn't be necessary because each
* strip is suppose to be terminated with CODE_EOI.
*/
#define NextCode(_tif, _sp, _bp, _code, _get) { \
if ((_sp)->dec_bitsleft < nbits) { \
TIFFWarning(_tif->tif_name, \
"LZWDecode: Strip %d not terminated with EOI code", \
_tif->tif_curstrip); \
_code = CODE_EOI; \
} else { \
_get(_sp,_bp,_code); \
(_sp)->dec_bitsleft -= nbits; \
} \
}
#else
#define NextCode(tif, sp, bp, code, get) get(sp, bp, code)
#endif
static int
LZWSetupDecode(TIFF* tif)
{
LZWCodecState* sp = DecoderState(tif);
static const char module[] = "LZWSetupDecode";
int code;
assert(sp != NULL);
if (sp->dec_codetab == NULL) {
sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t));
if (sp->dec_codetab == NULL) {
TIFFError(module, "No space for LZW code table");
return (0);
}
/*
* Pre-load the table.
*/
code = 255;
do {
sp->dec_codetab[code].value = (u_char) code;
sp->dec_codetab[code].firstchar = (u_char) code;
sp->dec_codetab[code].length = 1;
sp->dec_codetab[code].next = NULL;
} while (code--);
}
return (1);
}
/*
* Setup state for decoding a strip.
*/
static int
LZWPreDecode(TIFF* tif, tsample_t s)
{
LZWCodecState *sp = DecoderState(tif);
(void) s;
assert(sp != NULL);
/*
* Check for old bit-reversed codes.
*/
if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) {
#ifdef LZW_COMPAT
if (!sp->dec_decode) {
TIFFWarning(tif->tif_name,
"Old-style LZW codes, convert file");
/*
* Override default decoding methods with
* ones that deal with the old coding.
* Otherwise the predictor versions set
* above will call the compatibility routines
* through the dec_decode method.
*/
tif->tif_decoderow = LZWDecodeCompat;
tif->tif_decodestrip = LZWDecodeCompat;
tif->tif_decodetile = LZWDecodeCompat;
/*
* If doing horizontal differencing, must
* re-setup the predictor logic since we
* switched the basic decoder methods...
*/
(*tif->tif_setupdecode)(tif);
sp->dec_decode = LZWDecodeCompat;
}
sp->lzw_maxcode = MAXCODE(BITS_MIN);
#else /* !LZW_COMPAT */
if (!sp->dec_decode) {
TIFFError(tif->tif_name,
"Old-style LZW codes not supported");
sp->dec_decode = LZWDecode;
}
return (0);
#endif/* !LZW_COMPAT */
} else {
sp->lzw_maxcode = MAXCODE(BITS_MIN)-1;
sp->dec_decode = LZWDecode;
}
sp->lzw_nbits = BITS_MIN;
sp->lzw_nextbits = 0;
sp->lzw_nextdata = 0;
sp->dec_restart = 0;
sp->dec_nbitsmask = MAXCODE(BITS_MIN);
#ifdef LZW_CHECKEOS
sp->dec_bitsleft = tif->tif_rawcc << 3;
#endif
sp->dec_free_entp = sp->dec_codetab + CODE_FIRST;
/*
* Zero entries that are not yet filled in. We do
* this to guard against bogus input data that causes
* us to index into undefined entries. If you can
* come up with a way to safely bounds-check input codes
* while decoding then you can remove this operation.
*/
_TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t));
sp->dec_oldcodep = &sp->dec_codetab[-1];
sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1];
return (1);
}
/*
* Decode a "hunk of data".
*/
#define GetNextCode(sp, bp, code) { \
nextdata = (nextdata<<8) | *(bp)++; \
nextbits += 8; \
if (nextbits < nbits) { \
nextdata = (nextdata<<8) | *(bp)++; \
nextbits += 8; \
} \
code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \
nextbits -= nbits; \
}
static void
codeLoop(TIFF* tif)
{
TIFFError(tif->tif_name,
"LZWDecode: Bogus encoding, loop in the code table; scanline %d",
tif->tif_row);
}
static int
LZWDecode(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
{
LZWCodecState *sp = DecoderState(tif);
char *op = (char*) op0;
long occ = (long) occ0;
char *tp;
u_char *bp;
hcode_t code;
int len;
long nbits, nextbits, nextdata, nbitsmask;
code_t *codep, *free_entp, *maxcodep, *oldcodep;
(void) s;
assert(sp != NULL);
/*
* Restart interrupted output operation.
*/
if (sp->dec_restart) {
long residue;
codep = sp->dec_codep;
residue = codep->length - sp->dec_restart;
if (residue > occ) {
/*
* Residue from previous decode is sufficient
* to satisfy decode request. Skip to the
* start of the decoded string, place decoded
* values in the output buffer, and return.
*/
sp->dec_restart += occ;
do {
codep = codep->next;
} while (--residue > occ && codep);
if (codep) {
tp = op + occ;
do {
*--tp = codep->value;
codep = codep->next;
} while (--occ && codep);
}
return (1);
}
/*
* Residue satisfies only part of the decode request.
*/
op += residue, occ -= residue;
tp = op;
do {
int t;
--tp;
t = codep->value;
codep = codep->next;
*tp = (char) t;
} while (--residue && codep);
sp->dec_restart = 0;
}
bp = (u_char *)tif->tif_rawcp;
nbits = sp->lzw_nbits;
nextdata = sp->lzw_nextdata;
nextbits = sp->lzw_nextbits;
nbitsmask = sp->dec_nbitsmask;
oldcodep = sp->dec_oldcodep;
free_entp = sp->dec_free_entp;
maxcodep = sp->dec_maxcodep;
while (occ > 0) {
NextCode(tif, sp, bp, code, GetNextCode);
if (code == CODE_EOI)
break;
if (code == CODE_CLEAR) {
free_entp = sp->dec_codetab + CODE_FIRST;
nbits = BITS_MIN;
nbitsmask = MAXCODE(BITS_MIN);
maxcodep = sp->dec_codetab + nbitsmask-1;
NextCode(tif, sp, bp, code, GetNextCode);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?