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