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