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