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