1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include "general.h"
5 #include "fileoutput.h"
6 #include "lzw.h"
7 
8 /*
9 
10 This code is copyright 2004-2005 by Michael Kohn
11 You may not use any of this program in your own programs
12 without permission from Michael Kohn <mike@mikekohn.net>
13 
14 */
15 
compute_palette_gif(int length,unsigned int * picture,unsigned int * palette,unsigned int * palette_count)16 int compute_palette_gif(int length,unsigned int *picture,unsigned int *palette,unsigned int *palette_count)
17 {
18 int ptr,c,count;
19 
20   count=0;
21 
22   for (ptr=0; ptr<length; ptr++)
23   {
24     for (c=0; c<count; c++)
25     {
26       if (palette[c]==picture[ptr]) break;
27     }
28 
29     if (c==count)
30     {
31       if (count>=256)
32       {
33        *palette_count=count;
34         return 8;
35       }
36       palette[count++]=picture[ptr];
37     }
38   }
39 
40   *palette_count=count;
41 
42   c=1;
43 
44   while(c<=8)
45   {
46     if ((count>>c)==0) return c;
47     c++;
48   }
49 
50   return 8;
51 }
52 
53 /*
54 int get_color(int col, int *palette, int palette_count)
55 {
56 int d,c;
57 
58   for (c=0; c<palette_count; c++)
59   {
60     if (col==palette[c]) return c;
61   }
62 
63   for (d=0; d<255; d++)
64   {
65     for (c=0; c<palette_count; c++)
66     {
67       if (color_distance(col,palette[c])<=d) return c;
68     }
69   }
70 
71   return 0;
72 }
73 */
74 
write_gif_header(FILE * out,struct note_t * note)75 void write_gif_header(FILE *out, struct note_t *note)
76 {
77 
78 }
79 
write_gif_footer(FILE * out,struct note_t * note)80 void write_gif_footer(FILE *out, struct note_t *note)
81 {
82 struct gif_header_t gif_header;
83 struct compress_node_t node[4097];
84 unsigned char data_stream[256];
85 int curr_code_size,next_code;
86 int clear_code,eof_code,curr_code,data_size;
87 int c,max_colors,length,code_size,table_start_size,last_code;
88 unsigned int holding,ptr;
89 int bitptr,t;
90 unsigned char color;
91 
92   length=note->width*note->height;
93 
94   c=compute_palette_gif(length,note->picture,gif_header.color_map,(unsigned int *)&gif_header.colors);
95 
96   if (c<2) c=2; /* check this later */
97 
98   max_colors=1<<c;
99   code_size=c;
100 
101 /*
102 printf("colors=%d  bits=%d\n",gif_header.colors,c);
103 for (t=0; t<gif_header.colors; t++)
104 {
105   printf("%d: %6x\n",t,gif_header.color_map[t]);
106 }
107 */
108 
109 #ifdef DEBUG
110 printf("colors=%d  bits=%d\n",gif_header.colors,c);
111 #endif
112 
113   /* WRITE GIF HEADER */
114 
115   write_chars(out,"GIF87a");
116   write_word(out,note->width);
117   write_word(out,note->height);
118   putc(128+((code_size-1)<<4)+(code_size-1),out);
119   putc(0,out);
120   putc(0,out);
121 
122   for (c=0; c<max_colors; c++)
123   {
124     putc((gif_header.color_map[c]>>16),out);
125     putc(((gif_header.color_map[c]>>8)&255),out);
126     putc((gif_header.color_map[c]&255),out);
127   }
128 
129   putc(',',out);
130   write_word(out,0);
131   write_word(out,0);
132   write_word(out,note->width);
133   write_word(out,note->height);
134   putc((code_size-1),out);
135 
136   putc(code_size,out);
137 
138   for (c=0; c<max_colors; c++)
139   {
140     node[c].color=c;
141     node[c].right=c+1;
142     node[c].down=-1;
143   }
144 
145   /* node[c-1].right=-1; */
146 
147   clear_code=max_colors;
148   eof_code=max_colors+1;
149 
150 #ifdef DEBUG
151 printf("clear_code=%d\n",clear_code);
152 printf("eof_code=%d\n",eof_code);
153 #endif
154 
155   table_start_size=max_colors+2;
156   next_code=table_start_size;
157   curr_code_size=code_size+1;
158   curr_code=-1;
159   data_size=0;
160 
161 #ifdef DEBUG
162 printf("curr_code_size=%d\n",curr_code_size);
163 #endif
164 
165   holding=clear_code;
166   bitptr=curr_code_size;
167   ptr=0;
168 
169 #ifdef DEBUG
170 printf("length=%d\n",length);
171 #endif
172 
173   color=get_color(note->picture[ptr++],gif_header.color_map,gif_header.colors);
174   curr_code=color;
175   last_code=curr_code;
176 
177 #ifdef DEBUG
178 printf("curr_code=%d color=%d\n",curr_code,color);
179 #endif
180 
181   while (ptr<length)
182   {
183     color=get_color(note->picture[ptr++],gif_header.color_map,gif_header.colors);
184 
185 #ifdef DEBUG
186 printf("curr_code=%d color=%d\n",curr_code,color);
187 #endif
188 
189     if (node[curr_code].down==-1)
190     {
191       last_code=curr_code;
192       node[curr_code].down=next_code;
193     }
194       else
195     {
196       last_code=curr_code;
197       curr_code=node[curr_code].down;
198 
199       while(node[curr_code].color!=color && node[curr_code].right!=-1)
200       { curr_code=node[curr_code].right; }
201 
202       if (node[curr_code].color!=color && node[curr_code].right==-1)
203       { node[curr_code].right=next_code; }
204         else
205       { continue; }
206     }
207 
208 #ifdef DEBUG
209 printf("OUTPUT CODE %d  next_code=%d  color=%d\n",last_code,next_code,color);
210 #endif
211 
212     holding=holding+(last_code<<bitptr);
213     bitptr=bitptr+curr_code_size;
214 
215     node[next_code].right=-1;
216     node[next_code].down=-1;
217     node[next_code].color=color;
218     curr_code=color;
219 
220 
221     if ((next_code>>curr_code_size)!=0)
222     {
223       if (curr_code_size>=12)
224       {
225         holding=holding+(clear_code<<bitptr);
226         bitptr=bitptr+curr_code_size;
227 
228         for (c=0; c<max_colors; c++)
229         { node[c].down=-1; }
230 
231         next_code=table_start_size-1;
232         curr_code_size=code_size;
233         /* curr_code=0; */
234       }
235       curr_code_size++;
236     }
237 
238     next_code++;
239 
240 #ifdef DEBUG
241 printf("holding=0x%x   bitptr=%d  code_size=%d\n",holding,bitptr,curr_code_size);
242 #endif
243 
244     while (bitptr>=8)
245     {
246       data_stream[data_size++]=holding&255;
247       holding=holding>>8;
248       bitptr=bitptr-8;
249       if (data_size>=255)
250       {
251         putc(data_size,out);
252         t=0;
253         while(t!=data_size)
254         { t=t+fwrite(data_stream,1,data_size-t,out); }
255         data_size=0;
256       }
257     }
258   }
259 
260 #ifdef DEBUG
261 printf("Finishing up %d\n",curr_code);
262 #endif
263 
264   holding=holding+(curr_code<<bitptr);
265   bitptr=bitptr+curr_code_size;
266   holding=holding+(eof_code<<bitptr);
267   bitptr=bitptr+curr_code_size;
268 
269 
270   while (bitptr>0)
271   {
272     data_stream[data_size++]=holding&255;
273     holding=holding>>8;
274     bitptr=bitptr-8;
275     if (data_size>=255)
276     {
277       putc(data_size,out);
278       t=0;
279       while(t!=data_size)
280       { t=t+fwrite(data_stream,1,data_size-t,out); }
281       data_size=0;
282     }
283   }
284 
285 #ifdef DEBUG
286 printf("data_size=%d bitptr=%d\n",data_size,bitptr);
287 #endif
288 
289   if (data_size>0)
290   {
291     putc(data_size,out);
292     t=0;
293     while(t!=data_size)
294     { t=t+fwrite(data_stream,1,data_size-t,out); }
295   }
296 
297   putc(0,out);
298   putc(';',out);
299 
300 }
301 
302 
303