版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
楼主 |
发表于 2009-4-13 20:46
|
显示全部楼层
研究了好一段时间了终于明白了8成的原理了!这个东西可能没有多少人会看上的可能太复杂的吧呵呵,没所谓吧反正这个以后可以自己重温一下!下面是这个的C语言:6 E t) n+ J- @& G8 I* a
8 H. C; u: R% h6 }0 ~+ `% C1 ]/ a: u" t8 C, N
/* DECODE.C - An LZW decoder for GIF2 a0 H1 s/ Y4 W7 y- ~; S5 |
* Copyright (C) 1987, by Steven A. Bennett& A' W. Z. e+ |' D. U e( i
*
) [* p6 K8 E; `5 U* X * Permission is given by the author to freely redistribute and include+ `6 W, x& c# S
* this code in any program as long as this credit is given where due.
5 Y1 m' ?7 p& f3 K& F$ U *
8 }2 j8 \; Z5 d( l * In accordance with the above, I want to credit Steve Wilhite who wrote7 r% b- K' Q6 ~/ F0 W4 a
* the code which this is heavily inspired by...
' }$ |9 E5 I- b *, [: c+ ]# K3 e+ w
* GIF and 'Graphics Interchange Format' are trademarks (tm) of
6 ?9 ]' T) o' `: q; ~9 o& m* V * Compuserve, Incorporated, an H&R Block Company.; B; T( H: m% u" w1 a- `7 }% c
*0 u" ?0 o7 v6 ^; R7 S F- J3 C
* Release Notes: This file contains a decoder routine for GIF images
# t8 ?3 N: q) z# m0 V4 z * which is similar, structurally, to the original routine by Steve Wilhite.7 t1 t* I4 o: C! y Z* U
* It is, however, somewhat noticably faster in most cases.
( A' O* i3 m7 x6 ?; t6 } *& Q$ ]+ z( T N' P9 \
*/( `# f+ I. Z' t4 i) ?: K" k# I
# G7 ~) ]8 ~ h0 s, ?! r ]#include "std.h"
- F9 k- f# B5 r& J: K#include "errs.h"
' V& M9 Q5 i9 a: T5 w6 `" w$ m
: {: g9 R* l6 Z, {) {7 jIMPORT TEXT *malloc(); /* Standard C library allocation */( O% |* t K2 t+ A6 K1 L7 [
0 s* g" ^- w# {* m2 i9 p/* IMPORT INT get_byte()2 o& w& o- ^; ^ f! h U2 c
*
7 S1 A( r# K: F: D# x * - This external (machine specific) function is expected to return
% @9 Q F. c K: ^1 k. S! Q( X * either the next byte from the GIF file, or a negative number, as( H% }& N6 X1 v0 t: N
* defined in ERRS.H.
! [8 m" I* k7 U( a% ?. \# K+ q6 i: o */0 b8 s2 X6 t) V9 z: k) z6 W" |
IMPORT INT get_byte();
: {6 c1 B7 B4 ~) x4 h8 @* @, o( e. H1 J3 [9 G& A
/* IMPORT INT out_line(pixels, linelen)7 k% g( N. F. d3 M/ X
* UBYTE pixels[];/ s' v9 j7 m, d5 P/ s7 d6 } e
* INT linelen;
& [* T b% @3 t *( k) ~3 H3 S0 ?; j6 z, F9 R
* - This function takes a full line of pixels (one byte per pixel) and$ D) G+ m. K5 c
* displays them (or does whatever your program wants with them...). It! g: q |+ Q* t& r' ]' ?: A& U
* should return zero, or negative if an error or some other event occurs
9 W( y* [# Z" S* ]4 v * which would require aborting the decode process... Note that the length5 l5 M! K8 {2 x
* passed will almost always be equal to the line length passed to the9 ]. @8 m2 o% E! G" \( X
* decoder function, with the sole exception occurring when an ending code. c7 l5 a+ n# g4 ^: {9 V- k) b
* occurs in an odd place in the GIF file... In any case, linelen will be3 p% k* N [$ f) Q
* equal to the number of pixels passed...8 o) I) @2 I! ~8 L% N
*/8 ~9 _" C3 K' k3 {0 @
IMPORT INT out_line();
: V/ I0 A. S. s: T5 ^, P0 P( H1 l n+ U$ w7 O
/* IMPORT INT bad_code_count;
, {# `: t4 A! w% m, v% S *
& V) o, m8 ^9 W8 B; Z; M9 i * This value is the only other global required by the using program, and
X6 t( r/ A& D) N; a2 z3 L * is incremented each time an out of range code is read by the decoder.
3 N+ b6 q/ a' L$ |- D+ y" z7 r * When this value is non-zero after a decode, your GIF file is probably
5 J6 O7 R K% \ * corrupt in some way..." i/ W+ q6 g5 f; D
*/
+ [' q# S$ G9 c) g( i" ^( NIMPORT INT bad_code_count;4 Z: u: O* {! i5 r
3 W3 K) J7 X7 @7 i R' W
#define NULL 0L
& J0 B2 T+ J) R- A' D* }#define MAX_CODES 4095. r7 Q$ b: N) _: H& `
5 m* {/ K* T4 v5 Y, q/ J G2 d# ^/* Static variables */$ r$ q- ^" U8 J) Z
LOCAL WORD curr_size; /* The current code size */
' `% M- y; s" D, F) c6 i3 f7 r1 qLOCAL WORD clear; /* Value for a clear code */6 J2 J0 P- {2 E3 A* p6 B
LOCAL WORD ending; /* Value for a ending code */9 m% y) s5 S8 s' X9 t1 X
LOCAL WORD newcodes; /* First available code */
8 ?4 a% n. f5 r% n5 i6 r+ XLOCAL WORD top_slot; /* Highest code for current size */
7 S5 u3 S8 |* `* p% n$ R- bLOCAL WORD slot; /* Last read code */
2 Q0 @$ s- t4 Q
9 w$ R$ u5 ^2 h$ A$ f0 q$ @! ]* N/* The following static variables are used
) |5 o6 `$ \. b( H; D: ^ * for seperating out codes# @: O% c0 T7 ?- `+ b
*/
0 r. `" q5 B6 FLOCAL WORD navail_bytes = 0; /* # bytes left in block *// ]% {$ n/ ], b3 M
LOCAL WORD nbits_left = 0; /* # bits left in current byte */
1 y$ u0 o& y9 s" bLOCAL UTINY b1; /* Current byte */! o& g. |9 C- A( Q
LOCAL UTINY byte_buff[257]; /* Current block */
# x* A% f J' L3 a+ OLOCAL UTINY *pbytes; /* Pointer to next byte in block */
4 c9 f. N/ h1 f5 x- U
& F/ e" I3 j2 K( Y) e0 jLOCAL LONG code_mask[13] = {& u) v2 |8 e- F
0,& P6 x9 R# a5 y8 o4 f& e
0x0001, 0x0003,
1 u9 r- ~& T/ O0 G/ D# L+ k9 g 0x0007, 0x000F,$ V& J- Y, m+ a6 E, d& ]9 D$ ~
0x001F, 0x003F,. U! A% [# L; b* P
0x007F, 0x00FF,
n, l0 j* o z" X 0x01FF, 0x03FF,
( T& c" Y5 a2 n9 C3 c: K6 F 0x07FF, 0x0FFF
2 P8 k5 W( Q$ s0 v- `0 v3 J) I };
4 g/ ?8 ?: V% o" F) k, j( V4 g6 j1 ]7 g) v% f6 h
1 w% x' \. F& t6 B7 _" k; p# j8 ?2 w
/* This function initializes the decoder for reading a new image.
" ~, j; o% n1 s) R* @$ } */) e7 F8 a% v9 W3 i# l, A+ D; K
LOCAL WORD init_exp(size)
/ _) x7 z6 z$ H* ~ WORD size;
# ^0 ~+ l' i) |3 O Z" g {9 U: a2 {3 b+ u+ w& X8 q5 b0 p
curr_size = size + 1;8 q& L; | u" v9 ]+ ?4 D0 ?$ J z
top_slot = 1 << curr_size;6 ]9 P1 [! `# X4 p3 X
clear = 1 << size;
8 v5 M8 h1 A7 ^7 y. k ending = clear + 1;
7 b# d9 M) v) C8 @3 J9 O& h+ K slot = newcodes = ending + 1;! c: v3 c( Y) P, z
navail_bytes = nbits_left = 0;/ r$ F$ e9 C+ N$ V5 Y9 t. }' t5 p7 j8 k
return(0);( j* V2 r2 J, i
}0 }4 V9 |- w0 s+ S8 t7 o; K
' A9 g. _" A1 q2 g- o& K/* get_next_code()
% p* g( x! G; k& r7 A * - gets the next code from the GIF file. Returns the code, or else
! J, i: S7 h- {* H( v& ^7 w * a negative number in case of file errors...+ h1 W+ h) y. s) A
*/! V+ r( m j2 B# M& B0 n: [" b4 ]) A3 X
LOCAL WORD get_next_code()* M( Q8 ?0 u* d g4 }& i5 G
{# k6 K- u+ e) G( \- G7 @
WORD i, x;& E2 \- J" h6 s* h& M- S2 R+ Y
ULONG ret;
+ H8 n" D5 n4 ]6 r3 l- @- L, s& H5 N6 M! U" n) w; ?0 B
if (nbits_left == 0)
$ u( B L; O! i$ {* | h {
# t! p! g. O2 z- b if (navail_bytes <= 0)
% @5 F; V0 M( _+ s {
. e& V O9 x6 Z0 g7 V6 k# q+ o( l( v* ?% B7 |$ V# T) d) w! A
/* Out of bytes in current block, so read next block
& f/ A8 G V. S* I) y4 B/ {' N */
* h; Y$ l& c+ W, u pbytes = byte_buff;
3 `/ q4 k4 }7 k5 E6 F* x9 q if ((navail_bytes = get_byte()) < 0)
" O+ G1 m' m. P return(navail_bytes);- B J' I" [% ~# V$ |! U1 s/ _
else if (navail_bytes)/ t8 h7 [; C* J5 V1 {8 E: R) j
{- P8 G4 t( I7 P3 |; W9 }
for (i = 0; i < navail_bytes; ++i)& _% p W* V8 | n+ K5 k0 S
{
) _3 K2 A% j1 B if ((x = get_byte()) < 0)
* x/ n) x8 Y7 ?% d return(x);
c1 ~# k J% h byte_buff = x;
; G6 G" L& B5 F0 ~ }
' P7 M" F9 @% x( N' T }
2 C* x, |; i3 }' b5 A }
& o1 o3 J" |2 p1 [5 g4 e. b b1 = *pbytes++;
$ o! {/ q2 O5 \4 ` nbits_left = 8;
3 l# k4 b/ U* @. t0 V; { --navail_bytes;1 \0 Q6 X. u# W8 k5 y
}, N( I) Y" Z" [: `% L, L) _
+ Q. h- P) r, V8 x, v ret = b1 >> (8 - nbits_left);
# ]& }9 u. V% C while (curr_size > nbits_left)
- ] z* b" ?& n {
0 w. j$ H' B& a/ A6 {: X/ | if (navail_bytes <= 0)& q# m+ ~9 \+ x4 Y$ J( {. X
{( D$ U( ^0 A, d4 l% }& I6 f; ~. }
* A3 [- G& L: [9 j6 N3 F /* Out of bytes in current block, so read next block/ ~( J% r$ J, d3 z1 s! Q
*/
6 v, M9 L2 b2 C7 v2 ? pbytes = byte_buff;& ]' F1 X* r' J: n3 y6 K
if ((navail_bytes = get_byte()) < 0)% w$ a& O, Y8 C/ i5 V$ ]; y
return(navail_bytes);
4 x' g5 u; F Q! O else if (navail_bytes)
7 [/ Y( r. ^2 I* X, ?6 Q {- ]0 }& e* z1 E& F, n1 t- B
for (i = 0; i < navail_bytes; ++i)
0 i$ q3 s7 U5 H& I- f$ T* t { [$ T6 Y# {# \6 U! a
if ((x = get_byte()) < 0)
3 V& y5 D$ n' b7 |8 S9 q return(x);
% M" A; k# C4 r# A# j v byte_buff = x;
9 _! O+ L7 V, y; B: Q$ c }( R# [( O5 `4 P. y! \
}4 k! S( Y/ n( p$ R0 B
}' I2 m) z$ @+ c6 O9 j1 P
b1 = *pbytes++;- @/ a* S1 z' Y F7 q. ?" n: b" V+ z
ret |= b1 << nbits_left;" p. N0 m) b6 G- `7 \
nbits_left += 8;
4 v2 Q5 T ?4 E% G9 J9 \ --navail_bytes;4 t; H" l' i c7 l9 J6 k/ x' M, a! F( U
}; S$ D5 h/ s: @: v# S1 B5 n
nbits_left -= curr_size;- @/ q6 D. H& s% o6 U5 x R; M) v
ret &= code_mask[curr_size];& U6 b' N {$ x- _. I3 a4 m
return((WORD)(ret));# }$ U3 I# A; e* H/ h! {( C3 n
}
0 y+ \. C7 j7 T
( Q& A6 d" n8 e4 @/ O
' X9 U G1 F4 n; Y Q/* The reason we have these seperated like this instead of using
4 V0 O8 ^8 ?5 A- n/ l, |* c3 q * a structure like the original Wilhite code did, is because this/ x/ ~: T* i, O8 s: T
* stuff generally produces significantly faster code when compiled...9 p5 P5 x( }" z7 d+ R7 d4 T
* This code is full of similar speedups... (For a good book on writing
" J4 r" \7 b% O) _+ T: K * C for speed or for space optomisation, see Efficient C by Tom Plum,/ @4 g5 H0 j* x! K1 n* E2 W
* published by Plum-Hall Associates...)
( m2 x( w- g: }" J& j! m8 z7 _: ^1 o: e */9 \. e& e; ^* \$ {- y$ c& c; G
LOCAL UTINY stack[MAX_CODES + 1]; /* Stack for storing pixels */
3 {, ~6 ]: H4 F5 |: P' p, yLOCAL UTINY suffix[MAX_CODES + 1]; /* Suffix table */
; r9 D- `8 J# ^1 r) VLOCAL UWORD prefix[MAX_CODES + 1]; /* Prefix linked list */
3 r; i8 L# _" c$ f# V1 ?2 ~5 D7 ^) z2 u0 n: S* F2 | q& }
/* WORD decoder(linewidth)
7 b9 |' n4 S* R9 ?* L * WORD linewidth; * Pixels per line of image *5 q) X7 d _3 c
*) v) s5 b4 V) O9 P/ ?
* - This function decodes an LZW image, according to the method used9 Z& Z+ n2 ? J: N+ h
* in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
G0 f& i5 h% P* u" p+ P * will generate a call to out_line(), which is a user specific function
1 r' P# d: U' D; G * to display a line of pixels. The function gets it's codes from
- J0 s7 o* m3 ^ * get_next_code() which is responsible for reading blocks of data and2 M. r: M3 v) _# ~, G5 J6 L# m
* seperating them into the proper size codes. Finally, get_byte() is" ~8 r4 d0 ]. h! m- s
* the global routine to read the next byte from the GIF file.
$ J; g4 b" c# Y' K' p+ n8 g( c *
$ [1 C9 y+ D2 v* n4 x7 @ * It is generally a good idea to have linewidth correspond to the actual! V' o: K# U9 ?# `6 F
* width of a line (as specified in the Image header) to make your own% e3 h* s, D1 S( f
* code a bit simpler, but it isn't absolutely necessary.& i; v1 o3 d6 Q/ H* w9 E& S
*
" \; {) Z0 q3 Q3 M. m% ^+ i. I$ Y2 B * Returns: 0 if successful, else negative. (See ERRS.H)' p* u2 y" w1 Y& S" M- L6 V
*( O+ q C# h7 ~5 \5 i
*/) j9 D% J' c5 F( O8 R$ n' e! ^/ O
& ?! b! j0 G C! W# ]
WORD decoder(linewidth)( q2 [" i+ C$ b1 N: J# h3 f
WORD linewidth;2 x9 y- X8 e+ K% {7 {$ k
{
_# S5 x8 b# u* e7 | FAST UTINY *sp, *bufptr;
$ h0 C/ N0 W. y' |8 Q3 [ UTINY *buf;* [9 v9 ]& M! |
FAST WORD code, fc, oc, bufcnt;
6 `. C' B2 q6 ~! y# ^ C$ i WORD c, size, ret;
8 k7 a' c. g( b: Z$ x, O B
/ `& g& S& N( {7 Y; Y; J0 p /* Initialize for decoding a new image...6 ]. Q% l/ W+ R' c% G
*/
, A$ O. z# k: @* f4 J/ L if ((size = get_byte()) < 0)3 U; k! C6 m, e: f, @4 D
return(size); U' i, [3 h4 o! ]
if (size < 2 || 9 < size)9 `# N+ K; E, x3 d k
return(BAD_CODE_SIZE);. T# y& _, ]2 l3 U
init_exp(size);
* n9 _5 Q! J/ O9 I, q7 a% z5 D K; ?+ a6 O2 j5 W" V3 j+ ^" Y
/* Initialize in case they forgot to put in a clear code.
+ R, H0 I$ @! D' c, A * (This shouldn't happen, but we'll try and decode it anyway...)
+ f8 x' I1 F" f. @* O7 l) S% W9 h3 f: e4 N */& S& X- e: ~( z3 |2 }% g
oc = fc = 0;
: z% c H) M' T$ H. G+ B
0 e U5 A# a7 A% t* K /* Allocate space for the decode buffer: E# y/ i, C7 t& g5 C* N9 H% i" e
*/2 Z. O+ C+ t' M, b
if ((buf = (UTINY *)malloc(linewidth + 1)) == NULL)- Z0 ^5 q" ?; A z0 E/ [7 }, e
return(OUT_OF_MEMORY);
0 o' O( S, x; b# |3 U
5 }2 O- l, @. ^/ E) r2 j a /* Set up the stack pointer and decode buffer pointer
: O, F6 L# }3 Y' H* Y6 m( z */9 Q2 H3 J. t( C' A" c* T
sp = stack;+ N1 F' B8 z: n, G4 I) {
bufptr = buf;
! i' p! w4 }8 A$ H2 O$ h1 Z! { bufcnt = linewidth;0 u m9 J5 f- Y, ?: t
) d/ B, F' r- a( W B2 B3 b5 S
/* This is the main loop. For each code we get we pass through the
& _+ R2 p8 F* X * linked list of prefix codes, pushing the corresponding "character" for
% S& W" R0 m& Y. ~3 m& R3 }2 N * each code onto the stack. When the list reaches a single "character"1 ]1 l7 E& p" R' x1 G D, I: y
* we push that on the stack too, and then start unstacking each
. Y7 k& Z K# U+ [3 r% { g( N) L * character for output in the correct order. Special handling is W+ Q" G' b' |4 R9 C& f
* included for the clear code, and the whole thing ends when we get
/ J6 Z4 j% T1 X * an ending code.
{% c' ^5 R% l */
3 U9 r K& Y& C" M& f& f& |! ]% t while ((c = get_next_code()) != ending)
; a1 e/ Z: _$ w {' X5 W. ?) j/ s0 k1 G* L* ?; s
+ {% a% s: ^# ?+ t2 c0 c6 H4 p3 b( z
/* If we had a file error, return without completing the decode+ q( K$ _8 [( P& K$ P0 I# e
*/
9 D2 g4 n7 A: L0 D4 L9 d* A$ w if (c < 0)2 u5 G1 u% {5 {* |3 p* z& _
{
' C8 i. o* z( r% Z* t& q* X free(buf);2 P4 o: u4 w6 B- H( A
return(0);* U. \7 S7 N4 F; \ r+ d( I6 f
}
; s' u, z6 S& C+ x9 ~5 x- ]" R+ |( P" x x5 I
/* If the code is a clear code, reinitialize all necessary items.7 |8 W( A- @# K' H) G
*/. e1 v' k% B) c$ G$ w2 k
if (c == clear)
6 M9 L; g. I4 H: N) k, c {4 q7 m* v l* K+ G
curr_size = size + 1;
' z, N7 B6 c3 X) f, T slot = newcodes;
$ {" g5 Q: C) |& s top_slot = 1 << curr_size;# i# q5 i0 t" R4 y
1 X- x! k; X: ]
/* Continue reading codes until we get a non-clear code
6 N2 {: n! D' d6 S * (Another unlikely, but possible case...)
# I2 j/ l9 T8 r */8 E D0 }7 R/ r
while ((c = get_next_code()) == clear)
% J4 W2 |/ q% Z4 l; W. B: q/ o( G ;
$ J* J1 ^ Q: m2 O! {: o a# I6 C. X
/* If we get an ending code immediately after a clear code& W5 o' B) ] S1 c0 m! K& {
* (Yet another unlikely case), then break out of the loop.. ^: h; B9 h9 @- n! T6 s* t
*/$ }0 M* H* p7 I5 e& H! @" N
if (c == ending)" V* h8 G# {# F8 s! f
break;
/ S6 E8 [2 G3 T9 K6 N- E
/ s% I3 f. r1 ]+ D /* Finally, if the code is beyond the range of already set codes,8 A0 @' f7 ~( z6 l" n
* (This one had better NOT happen... I have no idea what will
! x T0 ~& A4 `2 L * result from this, but I doubt it will look good...) then set it9 U8 \, b3 d* f. O+ Y' e
* to color zero.
2 Z! m+ i$ \: `+ ]8 o3 _$ y */
: ]% J* {4 w- r7 E- V if (c >= slot)0 j+ Y9 Q4 M, R3 e* x8 Q6 g
c = 0;
3 W4 l6 H3 w1 H
: { ?: v0 P. k; U% z' v oc = fc = c;- ~3 {( s5 A1 c% W7 Y- p
# U6 \3 r) l' g, S8 v5 O /* And let us not forget to put the char into the buffer... And
3 [# E/ ~+ H6 r7 W * if, on the off chance, we were exactly one pixel from the end5 k, N Q& \5 t& ?
* of the line, we have to send the buffer to the out_line()
: ~7 e0 t* X, k) `; B" c* g * routine...! v% P) l+ _ _, ^' J
*/* c2 M) ]3 g: P0 _* x6 F
*bufptr++ = c;
) e* m0 f! u, w9 s* B8 i& Y" `7 V if (--bufcnt == 0). O' G9 E0 H' k% P
{* F! }- e) s- z3 \5 \
if ((ret = out_line(buf, linewidth)) < 0)
& b5 j, z* X3 r {: }) R" ^" ?8 A- U* m
free(buf);
: z# r( y0 ]& x2 @ return(ret);
6 g. m6 Y# L0 Q# a' L6 } }, N ^- E/ \6 B/ B& @! H1 r
bufptr = buf;
4 ~) D, M# @% N ]1 \0 | bufcnt = linewidth;
! Z+ }0 i) G8 V0 i" j }
0 l/ j8 X/ s; w8 d* |1 H }, k+ d/ R# P* Y, ^2 l7 ]
else
8 A, o) u8 M) U/ D {
# s6 G6 v) ?# M2 h' Z
; k5 I# t) q* C /* In this case, it's not a clear code or an ending code, so
( G& A1 w1 H% w8 u, B) K * it must be a code code... So we can now decode the code into
) W3 y- K( T( s" R" Q! ^3 i1 V * a stack of character codes. (Clear as mud, right?)3 |, e. z. k; P8 d* R9 Q3 m E
*/
; @5 U& L- L6 U! g3 @: q3 ^0 a code = c;
8 W9 F& a3 J5 J J3 v7 ]+ w9 k
: A. i; C' u4 Y, h& \ /* Here we go again with one of those off chances... If, on the! J3 @* l7 ]( M! y& O
* off chance, the code we got is beyond the range of those already9 J6 P B6 Z- N Y8 X1 z( m5 h
* set up (Another thing which had better NOT happen...) we trick* A" C4 t+ _2 ~8 P+ T% {
* the decoder into thinking it actually got the last code read.
/ h- g9 b$ N& `: R * (Hmmn... I'm not sure why this works... But it does...)! K8 k' }) s. Q& @" c& e5 i0 Y e
*/
- E* A& @' I# |, i if (code >= slot)
1 m+ O& y4 f" U1 j) ]+ ?7 A p {7 c! g* ?8 Q$ _/ D, Z
if (code > slot)
5 d. }- Z6 h) A1 U ++bad_code_count;+ [7 C& Y. |. G* {5 B
code = oc;& g4 J6 A: q! V1 z
*sp++ = fc;9 Z" r1 O M2 c# z- V% M7 j
}7 w- a) o+ r" e" X" Q0 R2 F: R
2 Y; @2 L* P: |& C$ n /* Here we scan back along the linked list of prefixes, pushing7 q* U* w, h! P7 {
* helpless characters (ie. suffixes) onto the stack as we do so.1 p# f- \" P# c
*/
. i* [8 H) G. V. U8 M; ` while (code >= newcodes)
; P' x& W, c4 \9 w- f$ {) ? {
- K% c5 V( q7 P *sp++ = suffix[code];
' E7 c* f8 x$ K- Z code = prefix[code];
4 _6 t* Q Y: K5 y/ C% N }
' v- W$ X+ A& E6 H8 [2 h7 U1 ~# E2 I
/* Push the last character on the stack, and set up the new
" T$ F% S4 a) p! _, w' J" i& R" ]: C0 t * prefix and suffix, and if the required slot number is greater# W7 x! W' l7 p9 Z* n
* than that allowed by the current bit size, increase the bit
' }, p9 _. c7 J7 ?' m * size. (NOTE - If we are all full, we *don't* save the new
. q7 i) f& `. J1 \: [ * suffix and prefix... I'm not certain if this is correct...
2 ]- i [- K' s5 K; O% d * it might be more proper to overwrite the last code...' \. w! Y& H) A2 t% A# t
*/) m$ p- V2 D: ? F
*sp++ = code;% g% o2 s$ D$ {! K
if (slot < top_slot)/ L1 B9 g" _& }* r
{6 L" U4 Z9 _$ o( O8 w% r
suffix[slot] = fc = code;
8 N. {: d3 _* z, W prefix[slot++] = oc;
1 D$ u: X2 `3 h oc = c;' i0 P7 j f; h( M6 n+ a
}
$ M% T- z" I+ o! } if (slot >= top_slot)
) ~( d/ B' R+ u/ k3 U if (curr_size < 12)
4 t- \$ E+ r3 C+ J7 x& A9 k {
6 u2 ]7 H& j- q# s7 O- l top_slot <<= 1;; Y1 ], w: c3 B5 ]. b, o1 e ]
++curr_size;
, W2 K) h! S! k- g6 B }
& H: k* Q- R: P- y1 H
3 b# B. D! P- G /* Now that we've pushed the decoded string (in reverse order)
4 o7 ^% R% p! M7 }: I$ m5 R% W V) x * onto the stack, lets pop it off and put it into our decode/ \5 X6 ^5 Z/ S8 M* ?2 p, X; N7 D
* buffer... And when the decode buffer is full, write another
) H% v/ X( _( [0 B1 g1 @! i * line...
/ s% Y# v: n( G* _ */
Q z5 P; _! e4 Z! _8 j3 D while (sp > stack)0 B% i: f5 i# ^& Z8 s; t
{2 W7 k" o7 F; y4 s g
*bufptr++ = *(--sp);- L: L. l/ S- k$ |& r @/ e
if (--bufcnt == 0)7 m# p9 \( C% Y$ s
{, E7 h( P6 y. w8 y3 b2 B
if ((ret = out_line(buf, linewidth)) < 0)
- B: \4 z/ ]7 i: t2 a0 f {
3 M4 z4 ?1 j6 J& u+ q free(buf);. H3 V/ o' j* g* V* i; |: R- H
return(ret);6 D; f Q8 C, a2 _4 ]9 I
}$ @& n- T/ x1 Z6 j) j! ~3 K1 Y% F6 s
bufptr = buf;
, a7 v- `: u4 U6 l0 j u) y bufcnt = linewidth; r* P& k4 U/ A" {* u
}
6 T5 s* @& N+ M }2 [: p+ U7 D% `) |% I
}
! Y2 e4 n" v5 _ [ }
& z% `& s$ f3 P0 t- d ret = 0;2 F. K+ J, t0 e; h9 @
if (bufcnt != linewidth)$ k6 C! T0 y/ [2 l; U5 O6 K, A
ret = out_line(buf, (linewidth - bufcnt));, B! U& g4 z S: L4 c! ^
free(buf);" p G4 B6 d/ Q
return(ret);
* Y" u7 r H9 Y6 z } |
|