1 /*
2 Modified by Go Watanabe.
3
4 - GIF loading code.
5
6 watanabe@papilio.tutics.tut.ac.jp
7
8 This source code based strongly on...
9
10 gif2ras.c - Converts from a Compuserve GIF(tm) image to a Sun Raster image.
11
12 Copyright (c) 1988, 1989 by Patrick J. Naughton
13
14 Author: Patrick J. Naughton
15 naughton@wind.sun.com
16
17 Permission to use, copy, modify, and distribute this software and its
18 documentation for any purpose and without fee is hereby granted,
19 provided that the above copyright notice appear in all copies and that
20 both that copyright notice and this permission notice appear in
21 supporting documentation.
22
23 This file is provided AS IS with no warranties of any kind. The author
24 shall have no liability with respect to the infringement of copyrights,
25 trade secrets or any patents by this file or any part thereof. In no
26 event will the author be liable for any lost revenue or profits or
27 other special, indirect and consequential damages.
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include "image.h"
34 #include "gif.h"
35
36 #ifndef SEEK_CUR
37 #define SEEK_CUR 1
38 #endif
39
40 extern int verbose;
41
42 static int EGA_palette[16][3] = {
43 {0,0,0}, {0,0,128}, {0,128,0}, {0,128,128},
44 {128,0,0}, {128,0,128}, {128,128,0}, {200,200,200},
45 {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255},
46 {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255},
47 };
48
49 /* work varable */
50 static u_char *data;
51 static u_char *pic8,*raster;
52 static int xc, yc, pass;
53 static int bit_offset,bit_buf;
54 static int prefix[4096],suffix[4096]; /* The hash table */
55 static int out_code[4097]; /* An output array */
56 static struct palette global_pal[256]; /* global_palette */
57
58 static inline unsigned
get_short(FILE * fp)59 get_short(FILE *fp)
60 {
61 unsigned c,c1;
62 c = getc(fp),c1 = getc(fp);
63 return c|(c1 << 8);
64 }
65
66 static void
aspect_extension(GifInfo * gi,FILE * fp)67 aspect_extension(GifInfo *gi, FILE *fp)
68 {
69 int sbsize,blocksize,aspect,aspden;
70
71 blocksize = getc(fp);
72 if (blocksize != 2)
73 fseek(fp,blocksize,SEEK_CUR);
74 else {
75 aspect = getc(fp);
76 aspden = getc(fp);
77 if (aspden > 0 && aspect > 0)
78 gi->normal_aspect = (float) aspect / aspden;
79 else {
80 gi->normal_aspect = 1.0;
81 aspect = aspden = 1;
82 }
83 if (verbose) {
84 fprintf(stderr,"GIF87 aspect: %d:%d = %f\n",
85 aspect, aspden,gi->normal_aspect);
86 }
87 }
88 while (sbsize = getc(fp),sbsize > 0)
89 fseek(fp,sbsize,SEEK_CUR);
90 }
91
92 static void
plain_text_extension(GifInfo * gi,FILE * fp)93 plain_text_extension(GifInfo *gi, FILE *fp)
94 {
95 int i,sbsize,ch;
96 int tgLeft,tgTop,tgWidth,tgHeight,cWidth,cHeight,fg,bg;
97
98 sbsize = getc(fp);
99 tgLeft = get_short(fp);
100 tgTop = get_short(fp);
101 tgWidth = get_short(fp);
102 tgHeight = get_short(fp);
103 cWidth = getc(fp);
104 cHeight = getc(fp);
105 fg = getc(fp);
106 bg = getc(fp);
107 fseek(fp,sbsize - 12,SEEK_CUR);
108
109 if (verbose)
110 fprintf(stderr,"PlainText\ntgrid=%d,%d %dx%d "
111 "cell=%dx%d col=%d,%d\n",
112 tgLeft,tgTop,tgWidth,tgHeight,cWidth,cHeight,fg,bg);
113
114 /* read (and ignore) data sub-blocks */
115 while (sbsize = getc(fp), sbsize >0) {
116 if (verbose) {
117 for (i = 0; i < sbsize; i++) {
118 ch = getc(fp);
119 putc(ch,stderr);
120 }
121 } else
122 fseek(fp,sbsize,SEEK_CUR);
123 }
124 if (verbose)
125 putc('\n',stderr);
126 }
127
128 static void
graphic_ctl_extension(GifInfo * gi,FILE * fp)129 graphic_ctl_extension(GifInfo *gi, FILE *fp)
130 {
131 int sbsize;
132 u_char flag;
133 u_char transparent;
134
135 sbsize = getc(fp); /* must 4 */
136
137 if (sbsize != 4){
138 fseek(fp,sbsize,SEEK_CUR);
139 goto end;
140 }
141
142 flag = getc(fp);
143 gi->delay_time = get_short(fp);
144 transparent = getc(fp);
145
146 if (verbose)
147 fprintf(stderr,"Graphic Control Extension: %x %d %x \n",
148 flag, gi->delay_time, transparent );
149
150 if (flag & 0x01) /* transparent */
151 gi->transparent_index = transparent;
152
153 gi->disposal_method = (flag >> 3) & 0x07;
154 gi->user_input_flag = (flag & 0x40)?1:0;
155
156
157 end:
158 while (sbsize = getc(fp),sbsize > 0)
159 fseek(fp,sbsize,SEEK_CUR);
160 }
161
162 static void
application_extension(GifInfo * gi,FILE * fp)163 application_extension(GifInfo *gi, FILE *fp)
164 {
165 int sbsize;
166 char buf[20];
167 sbsize = getc(fp);
168
169 if (sbsize == 11) {
170 fread(buf, 11, 1, fp);
171 sbsize = getc(fp);
172 if (!strncmp(buf,"NETSCAPE",8) || !strncmp(buf,"netscape",8)) {
173 if (sbsize == 3) {
174 getc(fp);
175 gi->loop_cnt = get_short(fp);
176 sbsize = getc(fp);
177 gi->loop_flag = 1;
178 if (verbose)
179 fprintf(stderr, "Netscape Loop Extension: %d\n",
180 gi->loop_cnt);
181 }
182 }
183 }
184
185 while (sbsize > 0) {
186 fseek(fp,sbsize,SEEK_CUR);
187 sbsize = getc(fp);
188 }
189 }
190
191 static void
ignore_extension(FILE * fp)192 ignore_extension(FILE *fp)
193 {
194 int sbsize;
195 while (sbsize = getc(fp),sbsize > 0)
196 fseek(fp,sbsize,SEEK_CUR);
197 }
198
199 static int
readCode(int n)200 readCode(int n)
201 {
202 int x = bit_buf;
203
204 while(n > bit_offset)
205 x |= *raster++ << bit_offset, bit_offset += 8;
206
207 bit_buf = x >> n;
208 bit_offset -= n;
209
210 return x;
211 }
212
213 /*
214 Fetch the next code from the raster data stream. The codes can be
215 any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
216 maintain our location in the Raster array as a BIT Offset. We compute
217 the byte Offset into the raster array by dividing this by 8, pick up
218 three bytes, compute the bit Offset into our 24-bit chunk, shift to
219 bring the desired code to the bottom, then mask it off and return it.
220 */
221
222 static void
doInterlace(GifInfo * gi,int * outcode,int n)223 doInterlace(GifInfo *gi, int *outcode,int n)
224 {
225 static int yc_inc[] = { 8,8,4 },
226 yc_next[] = { 4,2,1, },
227 pic_inc[] = { 7,7,3, };
228 retry:
229 switch(pass) {
230 case 0:
231 case 1:
232 case 2:
233 while(n--) {
234 *pic8++ = *outcode--;
235 if (++xc == gi->Width) {
236 xc = 0;
237 if ((yc += yc_inc[pass]) >= gi->Height) {
238 yc = yc_next[pass];
239 pic8 = (u_char *)data + yc * gi->Width;
240 pass++;
241 goto retry;
242 }
243 pic8 += pic_inc[pass] * gi->Width;
244 }
245 }
246 break;
247 case 3:
248 while(n--) {
249 *pic8++ = *outcode--;
250 if (++xc == gi->Width) {
251 xc = 0;
252 yc += 2;
253 pic8 += gi->Width;
254 }
255 }
256 break;
257 }
258 }
259
260 static int
decode_image(GifInfo * gi,ImageData * img,FILE * fp)261 decode_image(GifInfo *gi, ImageData *img, FILE *fp)
262 {
263 u_char *work;
264 int i,npixels,maxpixels,size;
265 int colormap_flag,interlace;
266 int code,current_code,old_code,in_code;
267 int code_size;
268
269 int clear_code,EOF_code,free_code,first_free;
270 int init_code_size,max_code,FinChar;
271 int out_count;
272 int read_mask; /* Code AND mask for current code size */
273
274 /* copy from global palette */
275 struct palette *p = image_alloc_palette(img,256);
276 for (i = 0; i < 256; i++)
277 *p++ = global_pal[i];
278
279 gi->LeftOfs = get_short(fp);
280 gi->TopOfs = get_short(fp);
281 gi->Width = get_short(fp);
282 gi->Height = get_short(fp);
283
284 if (!(data = image_alloc_data(img,gi->Width,gi->Height,8)))
285 return -1;
286
287 colormap_flag = getc(fp);
288 interlace = (colormap_flag & INTERLACEMASK);
289
290 if (verbose)
291 fprintf(stderr,"GIF Image:local image (%dx%d)\n",gi->Width,gi->Height);
292
293 /* read local colormap */
294 if (colormap_flag & 0x80) {
295 int colormap_size = 1 << ((colormap_flag & 7)+1);
296 struct palette *p = img->pal;
297
298 for (i = 0; i < colormap_size; i++,p++) {
299 p->r = getc(fp);
300 p->g = getc(fp);
301 p->b = getc(fp);
302 }
303 }
304
305 bit_offset = bit_buf = 0;
306 code_size = getc(fp);
307 clear_code = (1 << code_size);
308 EOF_code = clear_code + 1;
309 first_free =
310 free_code = clear_code + 2;
311
312 /* The GIF spec has it that the code size is the code size used to
313 compute the above values is the code size given in the file, but the
314 code size used in compression/decompression is the code size given in
315 the file plus one. (thus the ++).
316 */
317
318 init_code_size = ++code_size;
319 max_code = (1 << code_size);
320 read_mask = max_code - 1;
321
322 if (verbose) {
323 fprintf(stderr,"codesize %d init codesize %d\n",
324 code_size,init_code_size);
325 }
326
327 /* UNBLOCK:
328 Read the raster data. Here we just transpose it from the GIF array
329 to the Raster array, turning it from a series of blocks into one long
330 data stream, which makes life much easier for readCode().
331 */
332
333 work = (u_char *)malloc(maxpixels = gi->Width * gi->Height);
334 if(work == NULL) {
335 perror("malloc");
336 fprintf(stderr,"GIF Image load failed.\n");
337 return -1;
338 }
339
340 raster = work;
341 while(size = getc(fp),size >0) {
342 int read_size;
343 if (raster + size > work + maxpixels) {
344 char buf[256];
345
346 read_size = fread(buf,1,size,fp);
347 memcpy(raster,buf,maxpixels - (raster - work));
348 raster += read_size;
349 while(size = getc(fp),size > 0) {
350 read_size = fread(buf,1,size,fp);
351 raster += read_size;
352 }
353 fprintf(stderr,"Error:Illegal GIF file size\n");
354 break;
355 }
356 read_size = fread(raster,1,size,fp);
357 raster += read_size;
358 }
359
360 raster = work;
361
362 /*
363 Decompress the file, continuing until you see the GIF EOF code.
364 One obvious enhancement is to add checking for corrupt files here.
365 */
366
367 npixels = out_count = 0;
368 pic8 = (u_char *)data;
369 xc = yc = pass = 0;
370 old_code = code = readCode(code_size) & read_mask;
371 FinChar = code & gi->bit_mask;
372
373 while(code != EOF_code) {
374 if(code == clear_code) {
375 /*
376 Clear code sets everything back to its initial value,
377 then reads the immediately subsequent code as uncompressed data.
378 */
379 code_size = init_code_size;
380 max_code = (1 << code_size);
381 read_mask = max_code - 1;
382 free_code = first_free;
383 current_code = old_code = code = readCode(code_size)&read_mask;
384 FinChar = current_code & gi->bit_mask;
385
386 if(interlace)
387 doInterlace(gi, &FinChar,1);
388 else
389 *pic8++ = FinChar;
390
391 code = readCode(code_size) & read_mask;
392 if(++npixels >= maxpixels)
393 break;
394 else
395 continue;
396 }
397 /* If not a clear code, must be data:
398 save same as current_code and in_code */
399
400 /* If we're at maxcode and didn't get a clear, stop loading */
401 if(free_code >= 4096)
402 break;
403 current_code = in_code = code;
404
405 /* If greater or equal to free_code, not in the hash table yet;
406 repeat the last character decoded */
407
408 if(current_code >= free_code) {
409 current_code = old_code;
410 if(out_count > 4096) break;
411 out_code[out_count++] = FinChar;
412 }
413
414 /* Unless this code is raw data, pursue the chain pointed to
415 by current_code through the hash table to its end;
416 each code in the chain puts its associated output code
417 on the output queue. */
418
419 while(current_code > gi->bit_mask) {
420 if(out_count > 4096) break; /* corrupt file */
421 out_code[out_count++] = suffix[current_code];
422 current_code = prefix[current_code];
423 }
424 if(out_count > 4096) break;
425
426 /* The last code in the chain is treated as raw data. */
427
428 FinChar = current_code & gi->bit_mask;
429 out_code[out_count++] = FinChar;
430
431 /* Now we put the data out to the Output routine.
432 It's been stacked LIFO, so deal with it that way... */
433
434 /* safety thing: prevent exceeding range of 'pic8' */
435
436 if(npixels + out_count > maxpixels)
437 out_count = maxpixels - npixels;
438 if(interlace)
439 doInterlace(gi, out_code+out_count-1,out_count);
440 else {
441 for(i=out_count-1;i>=0;i--)
442 *pic8++ = out_code[i];
443 }
444 npixels += out_count;
445 out_count = 0;
446
447 /* Build the hash table on-the-fly. No table is stored in the file. */
448
449 prefix[free_code] = old_code;
450 suffix[free_code] = FinChar;
451 old_code = in_code;
452
453 /*
454 Point to the next slot in the table. If we exceed the current
455 max_code value, increment the code size unless it's already 12.
456 If it is, do nothing: the next code decompressed better be CLEAR
457 */
458 if (++free_code >= max_code) {
459 if(code_size < 12) {
460 code_size++;
461 max_code <<= 1;
462 read_mask = (1 << code_size) - 1;
463 }
464 }
465 code = readCode(code_size) & read_mask;
466 if (npixels >= maxpixels) break;
467 }
468 if (npixels != maxpixels) {
469 if(verbose)
470 fprintf(stderr,"This GIF file seems to be truncated. "
471 "Winging it.\n");
472 if(!interlace) {
473 /* clear->EOBuffer */
474 memset(pic8 + npixels,0, maxpixels - npixels);
475 }
476 }
477 free(work);
478
479 return 0;
480 }
481
482 int
gif_query_header(GifInfo * gi,FILE * fp)483 gif_query_header(GifInfo *gi, FILE *fp)
484 {
485 int i,aspect;
486 int ColorMapSize;
487 char Type[6];
488
489 int is89;
490 int Graphics_flag;
491
492 if(fread(Type,1,6,fp) != 6) {
493 perror("fread");
494 return -1;
495 }
496
497 if(strncmp(Type,"GIF87a",6) == 0)
498 is89 = 0;
499 else if(strncmp(Type,"GIF89a",6) == 0)
500 is89 = 1;
501 else return -1;
502
503 gi->GlobalWidth = get_short(fp);
504 gi->GlobalHeight = get_short(fp);
505 Graphics_flag = getc(fp);
506 gi->background_index = getc(fp);
507
508 ColorMapSize = 1 << ((Graphics_flag & 7)+1);
509 gi->bit_mask = ColorMapSize - 1;
510
511 gi->normal_aspect = 1.0f;
512 aspect = getc(fp);
513 if(aspect) {
514 if(is89) return -1;
515 gi->normal_aspect = (aspect + 15) / 64.0;
516 }
517
518 if (verbose)
519 fprintf(stderr,"debug:try to read gif %dx%d.\n",
520 gi->GlobalWidth,gi->GlobalHeight);
521
522 /* Read in global colormap. */
523 {
524 struct palette *p = global_pal;
525
526 if (Graphics_flag & COLORMAPMASK) {
527 if (verbose)
528 fprintf(stderr,"\tglobal pallette in colormap (%d).\n",
529 ColorMapSize);
530 for (i = 0; i < ColorMapSize; i++,p++) {
531 p->r = getc(fp);
532 p->g = getc(fp);
533 p->b = getc(fp);
534 }
535 } else {
536 if(verbose)
537 fprintf(stderr,"\tuse EGA pallette.\n");
538 for(i = 0; i < 256; i++) {
539 p->r = EGA_palette[i&15][0];
540 p->g = EGA_palette[i&15][1];
541 p->b = EGA_palette[i&15][2];
542 }
543 gi->background_index = -1;
544 }
545 }
546 return 0;
547 }
548
549 int
gif_read_stream_one(GifInfo * gi,ImageData * img,FILE * fp)550 gif_read_stream_one(GifInfo *gi, ImageData *img, FILE *fp)
551 {
552
553 /* ---------------------------------------------------------
554 possible things at this point are:
555 an application extension block
556 a comment extension block
557 an (optional) graphic control extension block
558 followed by either an image or a plaintext extension
559 */
560 for (;;) {
561 int block = getc(fp);
562
563 if (feof(fp))
564 break;
565
566 if(verbose)
567 fprintf(stderr,"block type 0x%02x:",block);
568
569 if (block == EXTENSION) { /* parse extension blocks */
570 int fn = getc(fp);
571
572 if(verbose)
573 fprintf(stderr," GIF extension type 0x%02x.\n", fn);
574 switch(fn) {
575 case 'R': /* GIF87 aspect extension */
576 aspect_extension(gi, fp);
577 break;
578 case 0xFE: /* Comment Extension */
579 ignore_extension(fp);
580 break;
581 case 0x01: /* PlainText Extension */
582 plain_text_extension(gi, fp);
583 break;
584 case 0xF9: /* Graphic Control Extension */
585 graphic_ctl_extension(gi, fp);
586 break;
587 case 0xFF: /* Application Extension */
588 application_extension(gi, fp);
589 break;
590 default: /* unknown extension */
591 if(verbose)
592 fprintf(stderr,
593 "GIF Image:unknown extension 0x%02x(ignored)\n", fn);
594 ignore_extension(fp);
595 }
596 } else if(block == IMAGESEP) {
597 if(verbose)
598 fprintf(stderr,"data chunk. now reading image..\n");
599 return decode_image(gi, img, fp);
600 } else if(block == TRAILER) { /* stop reading blocks */
601 if(verbose)
602 fprintf(stderr,"trailer\n");
603 break;
604 } else { /* unknown block type */
605 fprintf(stderr,"GIF Image:Unknown block type (0x%02x)"
606 "at %lx(ignored)\n", block,ftell(fp));
607 ignore_extension(fp);
608 }
609 }
610 return -1;
611 }
612
613 int
gif_read_stream(ImageData * img,FILE * fp)614 gif_read_stream(ImageData *img, FILE *fp)
615 {
616 GifInfo gi;
617
618 if (gif_query_header(&gi, fp) < 0)
619 return -1;
620 gi.transparent_index = -1;
621
622 if (gif_read_stream_one(&gi, img, fp) < 0)
623 return -1;
624
625 if (img->trans_flag == TRANS_AUTO && gi.transparent_index != -1) {
626 img->trans_flag = TRANS_INDEX;
627 img->trans_index = gi.transparent_index;
628 }
629
630 return 0;
631 }
632