1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "general.h"
6 #include "fileoutput.h"
7 #include "lzw.h"
8
9 /*
10
11 This code is copyright 2004-2005 by Michael Kohn
12 You may not use any of this program in your own programs
13 without permission from Michael Kohn <mike@mikekohn.net>
14
15 */
16
parse_gif(FILE * in,FILE * out,int out_type,struct note_t * note)17 int parse_gif(FILE *in, FILE *out, int out_type, struct note_t *note)
18 {
19 unsigned char temp_buffer[4096];
20 struct gif_header_t gif_header;
21 struct node_t node[4096];
22 int ch,t,r,x,y;
23 int code_size,curr_code_size,data_count;
24 unsigned int holding,bitptr;
25 int code,old_code,next_code,start_table_size;
26 int clear_code,eof_code,mask;
27 int ptr;
28
29 read_chars(in,temp_buffer,6);
30
31 if (strcmp(temp_buffer,"GIF89a")==0)
32 { gif_header.version=89; }
33 else
34 if (strcmp(temp_buffer,"GIF87a")==0)
35 { gif_header.version=87; }
36 else
37 {
38 printf("This is not a GIF.\n");
39 return -1;
40 }
41
42 /* READ GIF HEADER */
43
44 note->width=read_word(in);
45 note->height=read_word(in);
46 /* gif_header.width=read_word(in); */
47 /* gif_header.height=read_word(in); */
48 gif_header.resolution=getc(in);
49 gif_header.bgcolor=getc(in);
50 gif_header.aspect=getc(in);
51
52 gif_header.colors=1<<((gif_header.resolution&7)+1);
53
54 #ifdef DEBUG
55 printf("GIF HEADER\n");
56 printf("-----------------------------------------\n");
57 printf(" Signature: %s\n",temp_buffer);
58 printf(" Image size: %d x %d\n",note->width,note->height);
59 printf(" Resolution: 0x%02x colors=%d\n",gif_header.resolution,gif_header.colors);
60 printf(" BgColor: 0x%02x\n",gif_header.bgcolor);
61 printf(" Aspect: 0x%02x\n\n",gif_header.aspect);
62 #endif
63
64 /* IF THERE IS A GLOBAL COLOR MAP, READ IT */
65
66 if ((gif_header.resolution&128)==128)
67 {
68 for (t=0; t<gif_header.colors; t++)
69 {
70 gif_header.color_map[t]=(getc(in)<<16)+(getc(in)<<8)+getc(in);
71 }
72 }
73
74 /* READ EXTENSION BLOCKS */
75
76 while(1)
77 {
78 ch=getc(in);
79 if (ch=='!')
80 {
81 ch=getc(in);
82 while(1)
83 {
84 ch=getc(in);
85 if (ch==0) break;
86 for (t=0; t<ch; t++) getc(in);
87 }
88 }
89 else
90 { ungetc(ch,in); break; }
91 }
92
93 logo_header_route(out,note,out_type);
94
95 /* READ IN IMAGE DESCRIPTOR BLOCK */
96
97 t=getc(in);
98
99 if (t!=',')
100 {
101 printf("Expected ',' got %c at 0x%06x\n",t,(int)ftell(in));
102 return -1;
103 }
104
105 x=read_word(in);
106 y=read_word(in);
107 note->width=read_word(in);
108 note->height=read_word(in);
109 gif_header.flags=getc(in);
110
111 #ifdef DEBUG
112 printf("GIF IMAGE DESCRIPTION\n");
113 printf("-----------------------------------------\n");
114 printf("Coordinates: (%d,%d)\n",x,y);
115 printf(" Image size: %d x %d\n",note->width,note->height);
116 printf(" Flags: 0x%02x\n\n",gif_header.flags);
117 #endif
118
119 /* IF THERE IS A LOCAL COLOR MAP, READ IT */
120
121 if ((gif_header.flags&128)==128)
122 {
123 /* gif_header.colors=1<<((gif_header.flags&7)+1); */
124 x=1<<((gif_header.flags&7)+1);
125
126 for (t=0; t<x; t++)
127 {
128 gif_header.color_map[t]=(getc(in)<<16)+(getc(in)<<8)+getc(in);
129 }
130 }
131
132 code_size=getc(in);
133
134 #ifdef DEBUG
135 printf("code_size=%d\n",code_size);
136 #endif
137
138 start_table_size=(1<<code_size);
139
140 for (t=0; t<start_table_size; t++)
141 {
142 node[t].prev=-1;
143 node[t].color=t;
144 }
145
146 clear_code=t;
147 eof_code=t+1;
148 next_code=t+2;
149
150 code_size++;
151
152 x=0; y=0;
153 holding=0;
154 bitptr=0;
155 curr_code_size=code_size;
156 old_code=-1;
157
158 mask=(1<<curr_code_size)-1;
159 data_count=0;
160
161 ptr=0;
162
163 while(1)
164 {
165 /*
166 if (next_code>=4096)
167 {
168 //curr_code_size=code_size;
169 //next_code=start_table_size+2;
170 //old_code=-1;
171 //mask=(1<<curr_code_size)-1;
172 curr_code_size--;
173 mask=mask>>1;
174 printf("resetting\n");
175 }
176 */
177
178 while (bitptr<curr_code_size)
179 {
180 if (data_count==0)
181 {
182 if ((data_count=getc(in))==EOF) break;
183 if (data_count==0) break;
184 }
185 t=getc(in);
186 holding=holding+(t<<bitptr);
187 data_count--;
188 bitptr=bitptr+8;
189 }
190
191 if (t==EOF || data_count==EOF)
192 {
193 printf("EOF! %d\n",ptr);
194 break;
195 }
196 code=holding&mask;
197
198 #ifdef DEBUG
199 printf("holding=%d bitptr=%d mask=%d curr_code_size=%d\n",holding,bitptr,mask,curr_code_size);
200 printf(">> code=%d next_code=%d\n",code,next_code);
201 #endif
202
203 holding=holding>>curr_code_size;
204 bitptr=bitptr-curr_code_size;
205
206 if (code==clear_code)
207 {
208 curr_code_size=code_size;
209 next_code=start_table_size+2;
210 old_code=-1;
211 mask=(1<<curr_code_size)-1;
212
213 continue;
214 }
215 else
216 if (old_code==-1)
217 {
218 /* printf("0x%06x\n",gif_header.color_map[node[code].color]); */
219 note->picture[ptr++]=gif_header.color_map[node[code].color];
220 }
221 else
222 if (code==eof_code)
223 {
224 break;
225 }
226 else
227 {
228 if (code<next_code)
229 {
230 t=0;
231 r=code;
232 while(1)
233 {
234 temp_buffer[t++]=node[r].color;
235 if (node[r].prev==-1) break;
236 r=node[r].prev;
237 }
238
239 for (r=t-1; r>=0; r--)
240 {
241 /* printf("0x%06x\n",gif_header.color_map[temp_buffer[r]]); */
242 note->picture[ptr++]=gif_header.color_map[temp_buffer[r]];
243 }
244
245 node[next_code].color=temp_buffer[t-1];
246 node[next_code].prev=old_code;
247
248 if (next_code==mask && mask!=4095)
249 {
250 curr_code_size++;
251 mask=(1<<curr_code_size)-1;
252 }
253 next_code++;
254 }
255 else
256 {
257 t=0;
258 r=old_code;
259 while(1)
260 {
261 temp_buffer[t++]=node[r].color;
262 if (node[r].prev==-1) break;
263 r=node[r].prev;
264 }
265
266 node[next_code].color=temp_buffer[t-1];
267 node[next_code].prev=old_code;
268
269 #ifdef DEBUG
270 printf("adding %d to %d\n",temp_buffer[t],old_code);
271 #endif
272
273 if (next_code==mask && mask!=4095)
274 {
275 curr_code_size++;
276 mask=(1<<curr_code_size)-1;
277 }
278
279 next_code++;
280
281 for (r=t-1; r>=0; r--)
282 {
283 /* printf("0x%06x\n",gif_header.color_map[temp_buffer[r]]); */
284 note->picture[ptr++]=gif_header.color_map[temp_buffer[r]];
285 #ifdef DEBUG
286 /* printf("outputting %d\n",temp_buffer[r]); */
287 #endif
288 }
289
290 note->picture[ptr++]=gif_header.color_map[temp_buffer[t-1]];
291 }
292 }
293
294 old_code=code;
295 }
296
297 x=note->width*note->height;
298
299 for (t=ptr; t<x; t++)
300 {
301 note->picture[t]=gif_header.color_map[gif_header.bgcolor];
302 }
303
304 logo_footer_route(out,note,out_type);
305
306 return 0;
307 }
308
309