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