Rev 3811 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* |
2 | * gifdecode.c |
||
3 | * |
||
4 | * Copyright (c) 1997,1998,1999 by Hans Dinsen-Hansen |
||
5 | * Partly inspired by Helene Schulerud's inversrl_imageb.c of 13.2.1991. |
||
6 | * Copyright (c) 1995,1996 by Kevin Kadow |
||
7 | * Copyright (c) 1990,1991,1992,1993 by Mark Podlipec |
||
8 | * All rights reserved. |
||
9 | * |
||
10 | * This software may be freely copied, modified and redistributed |
||
11 | * without fee provided that this copyright notice is preserved |
||
12 | * intact on all copies and modified copies. |
||
13 | * |
||
14 | * There is no warranty or other guarantee of fitness of this software. |
||
15 | * It is provided solely "as is". The author(s) disclaim(s) all |
||
16 | * responsibility and liability with respect to this software's usage |
||
17 | * or its effect upon hardware or computer systems. |
||
18 | * |
||
19 | * The Graphics Interchange format (c) is the Copyright property of |
||
20 | * Compuserve Incorporated. Gif(sm) is a Service Mark property of |
||
21 | * Compuserve Incorporated. |
||
22 | * |
||
23 | */ |
||
24 | |||
25 | #include <stdio.h> |
||
26 | #include "whirlgif.h" |
||
27 | |||
28 | extern unsigned int debugFlag, verbose; |
||
29 | extern int count; |
||
30 | |||
31 | ULONG codeSize, expected, imgsize, mask, old, picI, rootCodeSize, first[MAXVAL]; |
||
32 | UBYTE *topGifBuff, *picture, gifBuff[MAXVAL], last[MAXVAL]; |
||
33 | int imgheight, imgwidth, interlaced, pass, |
||
34 | step[5]={7,7,3,1,0}, start[5]= {0,4,2,1,0}; |
||
35 | |||
36 | void GifDecode(FILE *fp, UBYTE *pix, GifImageHdr gifimage) |
||
37 | { UBYTE *chPos, firstCodeOut = 0, charBuff[256]; |
||
38 | ULONG CLEAR, EOI, bits = 0, code = 0, codeFeched, buffCount = 0; |
||
39 | int need = 0; |
||
40 | |||
41 | interlaced = gifimage.i; |
||
42 | imgwidth = gifimage.width; |
||
43 | imgheight = gifimage.height; |
||
44 | imgsize = imgwidth * imgheight; |
||
45 | picture = pix; |
||
46 | pass = picI = 0; |
||
47 | if ( debugFlag > 1 ) |
||
48 | fprintf(stderr, "(interlaced,imgwidth,imgheight,imgsize)=(%d,%d,%d,%d)\n", |
||
49 | interlaced, imgwidth, imgheight, imgsize); |
||
50 | |||
51 | rootCodeSize = Xgetc(fp); |
||
52 | CLEAR = 1 << rootCodeSize; |
||
53 | EOI = CLEAR + 1; |
||
54 | |||
55 | GifClearTable(); |
||
56 | |||
57 | if ( (buffCount = Xgetc(fp)) == 0 ) { |
||
3811 | kbelabas | 58 | sprintf((char*)charBuff, "End of image # %d before it began!\n", count); |
59 | TheEnd1((char*)charBuff); |
||
10 | reyssat | 60 | } |
61 | |||
62 | while(buffCount > 0) { |
||
63 | if ( fread(charBuff, 1, buffCount, fp) != buffCount ) { |
||
3811 | kbelabas | 64 | sprintf((char*)charBuff, "Premature end of file; Image # %d\n", count); |
65 | TheEnd1((char*)charBuff); |
||
10 | reyssat | 66 | } |
67 | for(chPos = charBuff; buffCount-- > 0; chPos++) { |
||
68 | need += (int) *chPos << bits; |
||
69 | bits += 8; |
||
70 | while (bits >= codeSize) { |
||
71 | code = need & mask; |
||
72 | need >>= codeSize; |
||
73 | bits -= codeSize; |
||
74 | if(code > expected) |
||
75 | TheEnd1("Neither LZW nor RunLength (new code != expected)\n"); |
||
76 | if (code == EOI) { |
||
77 | if (debugFlag > 1) fprintf(stderr, "Image # %d ends; buffCount=%d\n", |
||
78 | count, buffCount); |
||
79 | goto skipRest; |
||
80 | } |
||
81 | |||
82 | if(code == CLEAR) { |
||
83 | GifClearTable(); |
||
84 | continue; |
||
85 | } |
||
86 | if(old == MAXVAL) { /* i.e. first code after clear table */ |
||
87 | pix = GifSendData(pix, 1, &last[code]); |
||
88 | firstCodeOut = last[code]; |
||
89 | old = code; |
||
90 | continue; |
||
91 | } |
||
92 | codeFeched = code; |
||
93 | if(code == expected) { |
||
94 | *topGifBuff++ = firstCodeOut; |
||
95 | code = old; |
||
96 | } |
||
97 | while(code > CLEAR) { |
||
98 | *topGifBuff++ = last[code]; |
||
99 | code = first[code]; |
||
100 | } |
||
101 | |||
102 | *topGifBuff++ = firstCodeOut = last[code]; |
||
103 | first[expected] = old; |
||
104 | last[expected] = firstCodeOut; |
||
105 | if(expected < MAXVAL) expected++; |
||
106 | if(((expected & mask) == 0) && (expected < MAXVAL)) { |
||
107 | codeSize++; |
||
108 | mask += expected; |
||
109 | } |
||
110 | old = codeFeched; |
||
111 | pix = GifSendData(pix, topGifBuff - gifBuff, gifBuff); |
||
112 | topGifBuff = gifBuff; |
||
113 | |||
114 | } /* end of extracting codes */ |
||
115 | } /* end of reading a block of data */ |
||
116 | if ( (buffCount = Xgetc(fp)) == 0 ) { |
||
3811 | kbelabas | 117 | sprintf((char*)charBuff, "End of image # %d without EOI\n", count); |
118 | TheEnd1((char*)charBuff); |
||
10 | reyssat | 119 | } |
120 | } |
||
121 | |||
122 | skipRest: |
||
3814 | kbelabas | 123 | if (debugFlag) fprintf(stderr, "Ending GifDecode, written: %d=%d\n", |
124 | interlaced && (pix-picture == 0) ? imgsize : (int)(pix - picture), imgsize); |
||
10 | reyssat | 125 | return ; |
126 | } |
||
127 | |||
128 | UBYTE *GifSendData(UBYTE *pix, int bytes, UBYTE source[]) |
||
129 | |||
130 | { int j=0; |
||
131 | for(j = bytes - 1; j >= 0; j--) { |
||
132 | picI++; |
||
133 | *pix = source[j]; pix++; |
||
134 | if ( interlaced && (picI % imgwidth == 0) ) { |
||
135 | picI += ( imgwidth * step[pass]); |
||
136 | if (picI >= imgsize) { |
||
137 | picI = start[++pass] * imgwidth; |
||
138 | if ( debugFlag > 1 ) |
||
139 | fprintf(stderr, "De-interlacing: (picI,pass,start[pass])=(%d,%d,%d)\n", |
||
140 | picI, pass, start[pass]); |
||
141 | } |
||
142 | pix = &picture[picI]; |
||
143 | } |
||
144 | } |
||
145 | return(pix); |
||
146 | } |
||
147 | |||
148 | void GifClearTable() |
||
149 | { int i, maxi; |
||
150 | maxi = 1 << rootCodeSize; |
||
151 | expected = maxi + 2; |
||
152 | if (debugFlag > 1 ) fprintf(stderr, "Initing Table..."); |
||
153 | old = MAXVAL; |
||
154 | codeSize = rootCodeSize + 1; |
||
155 | mask = (1<<codeSize) - 1; |
||
156 | |||
157 | for(i = 0; i < maxi; i++) { |
||
158 | first[i] = MAXVAL; |
||
159 | last[i] = i & 0xff; |
||
160 | } |
||
161 | topGifBuff = gifBuff; |
||
162 | } |