filt_lzwd.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 255 行
C
255 行
#include "fitz-base.h"#include "fitz-stream.h"/* TODO: error checking */enum{ MINBITS = 9, MAXBITS = 12, NUMCODES = (1 << MAXBITS), LZW_CLEAR = 256, LZW_EOD = 257, LZW_FIRST = 258};typedef struct lzw_code_s lzw_code;struct lzw_code_s{ int prev; /* prev code (in string) */ unsigned short length; /* string len, including this token */ unsigned char value; /* data value */ unsigned char firstchar; /* first token of string */};typedef struct fz_lzwd_s fz_lzwd;struct fz_lzwd_s{ fz_filter super; int earlychange; unsigned int word; /* bits loaded from data */ int bidx; int resume; /* resume output of code from needout */ int codebits; /* num bits/code */ int code; /* current code */ int oldcode; /* previously recognized code */ int nextcode; /* next free entry */ lzw_code table[NUMCODES];};fz_error *fz_newlzwd(fz_filter **fp, fz_obj *params){ int i; FZ_NEWFILTER(fz_lzwd, lzw, lzwd); lzw->earlychange = 0; if (params) { fz_obj *obj; obj = fz_dictgets(params, "EarlyChange"); if (obj) lzw->earlychange = fz_toint(obj) != 0; } lzw->bidx = 32; lzw->word = 0; for (i = 0; i < 256; i++) { lzw->table[i].value = i; lzw->table[i].firstchar = i; lzw->table[i].length = 1; lzw->table[i].prev = -1; } for (i = 256; i < NUMCODES; i++) { lzw->table[i].value = 0; lzw->table[i].firstchar = 0; lzw->table[i].length = 0; lzw->table[i].prev = -1; } lzw->codebits = MINBITS; lzw->code = -1; lzw->nextcode = LZW_FIRST; lzw->oldcode = -1; lzw->resume = 0; return fz_okay;}voidfz_droplzwd(fz_filter *filter){}static inline void eatbits(fz_lzwd *lzw, int nbits){ lzw->word <<= nbits; lzw->bidx += nbits;}static inline fz_error * fillbits(fz_lzwd *lzw, fz_buffer *in){ while (lzw->bidx >= 8) { if (in->rp + 1 > in->wp) return fz_ioneedin; lzw->bidx -= 8; lzw->word |= *in->rp << lzw->bidx; in->rp ++; } return fz_okay;}static inline void unstuff(fz_lzwd *lzw, fz_buffer *in){ int i = (32 - lzw->bidx) / 8; while (i-- && in->rp > in->bp) in->rp --;}fz_error *fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out){ fz_lzwd *lzw = (fz_lzwd*)filter; unsigned char *s; int len; if (lzw->resume) { lzw->resume = 0; goto output; } while (1) { if (fillbits(lzw, in)) { if (in->eof) { if (lzw->bidx > 32 - lzw->codebits) { unstuff(lzw, in); return fz_iodone; } } else { return fz_ioneedin; } } lzw->code = lzw->word >> (32 - lzw->codebits); if (lzw->code == LZW_EOD) { eatbits(lzw, lzw->codebits); unstuff(lzw, in); return fz_iodone; } if (lzw->code == LZW_CLEAR) { int oldcodebits = lzw->codebits; lzw->codebits = MINBITS; lzw->nextcode = LZW_FIRST; lzw->code = lzw->word >> (32 - oldcodebits - MINBITS) & ((1 << MINBITS) - 1); if (lzw->code == LZW_EOD) { eatbits(lzw, oldcodebits + MINBITS); unstuff(lzw, in); return fz_iodone; } eatbits(lzw, oldcodebits + MINBITS); lzw->oldcode = lzw->code; if (out->wp + 1 > out->ep) { lzw->resume = 1; return fz_ioneedout; } *out->wp++ = lzw->code; continue; } eatbits(lzw, lzw->codebits); /* if stream starts without a clear code, oldcode is undefined... */ if (lzw->oldcode == -1) { lzw->oldcode = lzw->code; goto output; } /* add new entry to the code table */ lzw->table[lzw->nextcode].prev = lzw->oldcode; lzw->table[lzw->nextcode].firstchar = lzw->table[lzw->oldcode].firstchar; lzw->table[lzw->nextcode].length = lzw->table[lzw->oldcode].length + 1; if (lzw->code < lzw->nextcode) lzw->table[lzw->nextcode].value = lzw->table[lzw->code].firstchar; else lzw->table[lzw->nextcode].value = lzw->table[lzw->nextcode].firstchar; lzw->nextcode ++; if (lzw->nextcode >= (1 << lzw->codebits) - lzw->earlychange - 1) { lzw->codebits ++; if (lzw->codebits > MAXBITS) lzw->codebits = MAXBITS; /* FIXME */ } lzw->oldcode = lzw->code;output: /* code maps to a string, copy to output (in reverse...) */ if (lzw->code > 255) { if (out->wp + lzw->table[lzw->code].length > out->ep) { lzw->resume = 1; return fz_ioneedout; } len = lzw->table[lzw->code].length; s = out->wp + len; do { *(--s) = lzw->table[lzw->code].value; lzw->code = lzw->table[lzw->code].prev; } while (lzw->code >= 0 && s > out->wp); out->wp += len; } /* ... or just a single character */ else { if (out->wp + 1 > out->ep) { lzw->resume = 1; return fz_ioneedout; } *out->wp++ = lzw->code; } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?