1 /*
2  * xvgif.c  -  GIF loading code for 'xv'.  Based strongly on...
3  *
4  * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
5  *
6  * Copyright (c) 1988, 1989 by Patrick J. Naughton
7  *
8  * Author: Patrick J. Naughton
9  * naughton@wind.sun.com
10  *
11  * Permission to use, copy, modify, and distribute this software and its
12  * documentation for any purpose and without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and that
14  * both that copyright notice and this permission notice appear in
15  * supporting documentation.
16  *
17  * This file is provided AS IS with no warranties of any kind.  The author
18  * shall have no liability with respect to the infringement of copyrights,
19  * trade secrets or any patents by this file or any part thereof.  In no
20  * event will the author be liable for any lost revenue or profits or
21  * other special, indirect and consequential damages.
22  *
23  */
24 
25 
26 #include "xv.h"
27 
28 typedef int boolean;
29 
30 #define NEXTBYTE (*dataptr++)
31 #define SKIPBYTE (dataptr++)	/* quiet some compiler warnings */
32 #define EXTENSION     0x21
33 #define IMAGESEP      0x2c	/* a.k.a. Image Descriptor */
34 #define TRAILER       0x3b
35 #define INTERLACEMASK 0x40
36 #define COLORMAPMASK  0x80
37 
38 
39 
40 static FILE *fp;
41 
42 static int
43     BitOffset = 0,		/* Bit Offset of next code */
44     XC = 0, YC = 0,		/* Output X and Y coords of current pixel */
45     Pass = 0,			/* Used by output routine if interlaced pic */
46     OutCount = 0,		/* Decompressor output 'stack count' */
47     RWidth, RHeight,		/* screen dimensions */
48     Width, Height,		/* image dimensions */
49     LeftOfs, TopOfs,		/* image offset */
50     BitsPerPixel,		/* Bits per pixel, read from GIF header */
51 /*  BytesPerScanline,	*/	/* bytes per scanline in output raster */
52     ColorMapSize,		/* number of colors */
53     Background,			/* background color */
54     Transparent,		/* transparent color (GRR 19980314) */
55     CodeSize,			/* Code size, read from GIF header */
56     InitCodeSize,		/* Starting code size, used during Clear */
57     Code,			/* Value returned by ReadCode */
58     MaxCode,			/* limiting value for current code size */
59     ClearCode,			/* GIF clear code */
60     EOFCode,			/* GIF end-of-information code */
61     CurCode, OldCode, InCode,	/* Decompressor variables */
62     FirstFree,			/* First free code, generated per GIF spec */
63     FreeCode,			/* Decompressor, next free slot in hash table */
64     FinChar,			/* Decompressor variable */
65     BitMask,			/* AND mask for data size */
66     ReadMask,			/* Code AND mask for current code size */
67     Misc,                       /* miscellaneous bits (interlace, local cmap)*/
68     GlobalBitsPerPixel,		/* may have local colormap of different size */
69     GlobalColorMapSize,		/*   (ditto)  */
70     GlobalBitMask;		/*   (ditto)  */
71 
72 
73 static boolean Interlace, HasGlobalColormap;
74 
75 static byte *RawGIF;		/* The heap array to hold it, raw */
76 static byte *Raster;		/* The raster data stream, unblocked */
77 static byte *pic8;
78 
79     /* The hash table used by the decompressor */
80 static int Prefix[4096];
81 static int Suffix[4096];
82 
83     /* An output array used by the decompressor */
84 static int OutCode[4097];
85 
86 static int gif89 = 0;
87 static const char *id87 = "GIF87a";
88 static const char *id89 = "GIF89a";
89 
90 static int const EGApalette[16][3] = {
91   {0,0,0},       {0,0,128},     {0,128,0},     {0,128,128},
92   {128,0,0},     {128,0,128},   {128,128,0},   {200,200,200},
93   {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255},
94   {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} };
95 
96 
97 static int   readImage   PARM((PICINFO *));
98 static int   readCode    PARM((void));
99 static void  doInterlace PARM((int));
100 static int   gifError    PARM((PICINFO *, const char *));
101 static void  gifWarning  PARM((const char *));
102 
103 static int         filesize;
104 static const char *bname;
105 static byte       *dataptr;
106 
107 
108 /*****************************/
LoadGIF(fname,pinfo)109 int LoadGIF(fname, pinfo)
110      char *fname;
111      PICINFO *pinfo;
112 /*****************************/
113 {
114   /* returns '1' if successful */
115 
116   register byte  ch, *origptr;
117   register int   i, block;
118   int            aspect;
119   char tmpname[256];
120   byte r[256], g[256], b[256];
121 
122   /* initialize variables */
123   BitOffset = XC = YC = OutCount = 0;
124   Pass = -1;
125   RawGIF = Raster = pic8 = NULL;
126   gif89 = 0;
127   Transparent = -1;
128 
129   pinfo->pic     = (byte *) NULL;
130   pinfo->comment = (char *) NULL;
131   pinfo->numpages= 0;
132 
133   bname = BaseName(fname);
134   fp = xv_fopen(fname,"r");
135   if (!fp) return ( gifError(pinfo, "can't open file") );
136 
137 
138   /* find the size of the file */
139   fseek(fp, 0L, 2);
140   filesize = ftell(fp);
141   fseek(fp, 0L, 0);
142 
143   if (filesize + 256 < filesize)
144     return( gifError(pinfo, "GIF file size is too large") );
145 
146   /* the +256's are so we can read truncated GIF files without fear of
147      segmentation violation */
148   if (!(dataptr = RawGIF = (byte *) calloc((size_t) filesize+256, (size_t) 1)))
149     FatalError("LoadGIF: not enough memory to read GIF file");
150 
151   if (!(Raster = (byte *) calloc((size_t) filesize+256,(size_t) 1)))
152     FatalError("LoadGIF: not enough memory to read GIF file");
153 
154   if (fread(dataptr, (size_t) filesize, (size_t) 1, fp) != 1)
155     return( gifError(pinfo, "GIF data read failed") );
156   fclose(fp);
157 
158   origptr = dataptr;
159 
160   if      (strncmp((char *) dataptr, id87, (size_t) 6)==0) gif89 = 0;
161   else if (strncmp((char *) dataptr, id89, (size_t) 6)==0) gif89 = 1;
162   else    return( gifError(pinfo, "not a GIF file"));
163 
164   dataptr += 6;
165 
166   /* Get variables from the GIF screen descriptor */
167 
168   ch = NEXTBYTE;
169   RWidth = ch + 0x100 * NEXTBYTE;	/* screen dimensions... not used. */
170   ch = NEXTBYTE;
171   RHeight = ch + 0x100 * NEXTBYTE;
172   if (DEBUG) fprintf(stderr,"GIF89 logical screen = %d x %d\n",RWidth,RHeight);
173 
174   ch = NEXTBYTE;
175   HasGlobalColormap = ((ch & COLORMAPMASK) ? True : False);
176 
177   /* GRR 20070318:  fix decoding bug when global and local color-table sizes
178    *                differ */
179   GlobalBitsPerPixel = BitsPerPixel = (ch & 7) + 1;
180   GlobalColorMapSize = ColorMapSize = numcols = 1 << BitsPerPixel;
181   GlobalBitMask = BitMask = ColorMapSize - 1;
182 
183   Background = NEXTBYTE;		/* background color... not used. */
184 
185   aspect = NEXTBYTE;
186   if (aspect) {
187 #if 0
188     if (!gif89) return(gifError(pinfo,"corrupt GIF file (screen descriptor)"));
189     else normaspect = (float) (aspect + 15) / 64.0;   /* gif89 aspect ratio */
190 #else
191     normaspect = (float) (aspect + 15) / 64.0;   /* gif89 aspect ratio */
192 #endif
193     if (DEBUG) fprintf(stderr,"GIF89 aspect = %f\n", normaspect);
194     /* FIXME:  apparently this _should_ apply to all frames in a multi-image
195      *         GIF (i.e., PgUp/PgDn), but it doesn't */
196   }
197 
198 
199   /* Read in global colormap. */
200 
201   if (HasGlobalColormap)
202     for (i=0; i<ColorMapSize; i++) {
203       r[i] = NEXTBYTE;
204       g[i] = NEXTBYTE;
205       b[i] = NEXTBYTE;
206     }
207   else {  /* no _global_ colormap in GIF file (but may have local one(s)) */
208     /* put std EGA palette (repeated 16 times) into colormap, for lack of
209        anything better to do at the moment */
210 
211     for (i=0; i<256; i++) {
212       r[i] = EGApalette[i&15][0];
213       g[i] = EGApalette[i&15][1];
214       b[i] = EGApalette[i&15][2];
215     }
216   }
217   memcpy(pinfo->r, r, sizeof r);
218   memcpy(pinfo->g, g, sizeof g);
219   memcpy(pinfo->b, b, sizeof b);
220 
221   if (DEBUG > 1) {
222     fprintf(stderr,"  global color table%s:\n",
223       HasGlobalColormap? "":" (repeated EGA palette)");
224     for (i=0; i<ColorMapSize; i++) {
225       fprintf(stderr,"    (%3d  %02x,%02x,%02x)\n", i, pinfo->r[i],
226         pinfo->g[i], pinfo->b[i]);
227     }
228   }
229 
230   /* possible things at this point are:
231    *   an application extension block
232    *   a comment extension block
233    *   an (optional) graphic control extension block
234    *       followed by either an image
235    *	   or a plaintext extension
236    */
237 
238   while (1) {
239     block = NEXTBYTE;
240 
241     if (DEBUG) fprintf(stderr,"LoadGIF: ");
242 
243     if (block == EXTENSION) {  /* parse extension blocks */
244       int i, fn, blocksize, aspnum, aspden;
245 
246       /* read extension block */
247       fn = NEXTBYTE;
248 
249       if (DEBUG) fprintf(stderr,"GIF extension type 0x%02x\n", fn);
250 
251       if (fn == 'R') {                  /* GIF87 aspect extension */
252 	int sbsize;
253 
254 	blocksize = NEXTBYTE;
255 	if (blocksize == 2) {
256 	  aspnum = NEXTBYTE;
257 	  aspden = NEXTBYTE;
258 	  if (aspden>0 && aspnum>0)
259 	    normaspect = (float) aspnum / (float) aspden;
260 	  else { normaspect = 1.0;  aspnum = aspden = 1; }
261 
262 	  if (DEBUG) fprintf(stderr,"GIF87 aspect extension: %d:%d = %f\n\n",
263 			     aspnum, aspden,normaspect);
264 	}
265 	else {
266 	  for (i=0; i<blocksize; i++) SKIPBYTE;
267 	}
268 
269 	while ((sbsize=NEXTBYTE)>0) {  /* eat any following data subblocks */
270 	  for (i=0; i<sbsize; i++) SKIPBYTE;
271 	}
272       }
273 
274 
275       else if (fn == 0xFE) {  /* Comment Extension */
276 	int   ch, j, sbsize, cmtlen;
277 	byte *ptr1, *cmt, *cmt1, *sp;
278 
279 	cmtlen = 0;
280 	ptr1 = dataptr;      /* remember start of comments */
281 
282 	/* figure out length of comment */
283 	do {
284 	  sbsize = NEXTBYTE;
285 	  cmtlen += sbsize;
286 	  for (j=0; j<sbsize; j++) ch = NEXTBYTE;
287 	} while (sbsize);
288 
289 
290 	if (cmtlen>0) {   /* build into one un-blocked comment */
291 	  /* this can overflow iff cmtlen == 2G - 1, but then filesize
292 	   * would have to be > 2GB, which was disallowed above */
293 	  cmt = (byte *) malloc((size_t) (cmtlen + 1));
294 	  if (!cmt) FatalError("LoadGIF: couldn't malloc space for comments");
295 	  /* else */ {
296 	    sp = cmt;
297 	    do {
298 	      sbsize = (*ptr1++);
299 	      for (j=0; j<sbsize; j++, sp++, ptr1++) *sp = *ptr1;
300 	    } while (sbsize);
301 	    *sp = '\0';
302 
303 	    if (pinfo->comment) {    /* have to strcat onto old comments */
304 	      cmt1 = (byte *) malloc(strlen(pinfo->comment) + cmtlen + 2);
305 	      if (!cmt1) {
306 		free(cmt);
307 	        FatalError("LoadGIF: couldn't malloc space for comments");
308 	      }
309 	      /* else */ {
310 		strcpy((char *) cmt1, (char *) pinfo->comment);
311 		strcat((char *) cmt1, (char *) "\n");
312 		strcat((char *) cmt1, (char *) cmt);
313 		free(pinfo->comment);
314 		free(cmt);
315 		pinfo->comment = (char *) cmt1;
316 	      }
317 	    }
318 	    else pinfo->comment = (char *) cmt;
319 	  }  /* if (cmt) */
320 	}  /* if cmtlen>0 */
321       }
322 
323 
324       else if (fn == 0x01) {  /* PlainText Extension */
325 	int j,sbsize,ch;
326 	int tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg;
327 
328 	SetISTR(ISTR_INFO, "%s:  %s", bname,
329 		"PlainText extension found in GIF file.  Ignored.");
330 
331 	sbsize   = NEXTBYTE;
332 	tgLeft   = NEXTBYTE;  tgLeft   += (NEXTBYTE)<<8;
333 	tgTop    = NEXTBYTE;  tgTop    += (NEXTBYTE)<<8;
334 	tgWidth  = NEXTBYTE;  tgWidth  += (NEXTBYTE)<<8;
335 	tgHeight = NEXTBYTE;  tgHeight += (NEXTBYTE)<<8;
336 	cWidth   = NEXTBYTE;
337 	cHeight  = NEXTBYTE;
338 	fg       = NEXTBYTE;
339 	bg       = NEXTBYTE;
340 	i=12;
341 	for ( ; i<sbsize; i++) SKIPBYTE;   /* read rest of first subblock */
342 
343 	if (DEBUG) fprintf(stderr,
344 	   "PlainText: tgrid=%d,%d %dx%d  cell=%dx%d  col=%d,%d\n",
345 	   tgLeft, tgTop, tgWidth, tgHeight, cWidth, cHeight, fg, bg);
346 
347 	/* read (and ignore) data sub-blocks */
348 	do {
349 	  j = 0;
350 	  sbsize = NEXTBYTE;
351 	  while (j<sbsize) {
352 	    ch = NEXTBYTE;  j++;
353 	    if (DEBUG) fprintf(stderr,"%c", ch);
354 	  }
355 	} while (sbsize);
356 	if (DEBUG) fprintf(stderr,"\n\n");
357       }
358 
359 
360       else if (fn == 0xF9) {  /* Graphic Control Extension */
361 	int j, sbsize;
362 
363 	if (DEBUG) fprintf(stderr,"Graphic Control extension\n\n");
364 
365 	SetISTR(ISTR_INFO, "%s:  %s", bname,
366 		"Graphic Control Extension ignored.");
367 
368 	/* read (and ignore) data sub-blocks, unless compositing with
369          * user-defined background */
370 	do {
371 	  j = 0;
372 	  sbsize = NEXTBYTE;
373 	  /* GRR 19980314:  get transparent index out of block */
374 	  if (have_imagebg && sbsize == 4 && Transparent < 0) {
375 	    byte packed_fields = NEXTBYTE;
376 
377 	    j++;
378 	    SKIPBYTE;  j++;
379 	    SKIPBYTE;  j++;
380 	    if (packed_fields & 1) {
381 	      Transparent = NEXTBYTE;
382 	      j++;
383 	    }
384 	  }
385 	  while (j<sbsize) {
386 	    SKIPBYTE;  j++;
387 	  }
388 	} while (sbsize);
389       }
390 
391 
392       else if (fn == 0xFF) {  /* Application Extension */
393 	int j, sbsize;
394 
395 	if (DEBUG) fprintf(stderr,"Application extension\n\n");
396 
397 	/* read (and ignore) data sub-blocks */
398 	do {
399 	  j = 0; sbsize = NEXTBYTE;
400 	  while (j<sbsize) { SKIPBYTE;  j++; }
401 	} while (sbsize);
402       }
403 
404 
405       else { /* unknown extension */
406 	int j, sbsize;
407 
408 	if (DEBUG) fprintf(stderr,"unknown GIF extension 0x%02x\n\n", fn);
409 
410 	SetISTR(ISTR_INFO,
411 		"%s:  Unknown extension 0x%02x in GIF file.  Ignored.",
412 		bname, fn);
413 
414 	/* read (and ignore) data sub-blocks */
415 	do {
416 	  j = 0; sbsize = NEXTBYTE;
417 	  while (j<sbsize) { SKIPBYTE;  j++; }
418 	} while (sbsize);
419       }
420     }
421 
422 
423     else if (block == IMAGESEP) {
424       if (DEBUG) fprintf(stderr, "imagesep (page=%d)\n", pinfo->numpages+1);
425       if (DEBUG) fprintf(stderr, "  at start: offset=0x%lx\n",
426                          (unsigned long)(dataptr-RawGIF));
427 
428       BitOffset = XC = YC = Pass = OutCount = 0;
429 
430       if (pinfo->numpages > 0) {   /* do multipage stuff */
431 	if (pinfo->numpages == 1) {    /* first time only... */
432 	  xv_mktemp(pinfo->pagebname, "xvpgXXXXXX"); // a.k.a. close(mkstemp())
433 	  if (pinfo->pagebname[0] == '\0') {
434 	    ErrPopUp("LoadGIF: Unable to create temporary filename???",
435 			"\nHow unlikely!");
436 	    return 0;
437 	  }
438 	  /* GRR 20070328:  basename file doesn't go away, at least on Linux
439            *  (though all appended-number ones do); ergo, open for reading (see
440            *  if it's there), close, and explicitly unlink() if necessary */
441           /* GRR 20070506:  could/should call KillPageFiles() (xv.c) instead */
442 	  fp = xv_fopen(pinfo->pagebname, "r");
443 	  if (fp) {
444 	    fclose(fp);
445 	    unlink(pinfo->pagebname);  /* no errors during testing */
446 	  }
447 	}
448 	sprintf(tmpname, "%s%d", pinfo->pagebname, pinfo->numpages);
449 	fp = xv_fopen(tmpname, "w");
450 	if (!fp) {
451 	  ErrPopUp("LoadGIF: Unable to open temp file", "\nDang!");
452 	  return 0;
453 	}
454 	if (WriteGIF(fp, pinfo->pic, pinfo->type, pinfo->w, pinfo->h, pinfo->r,
455 		 pinfo->g, pinfo->b, numcols, pinfo->colType, NULL)) {
456 	  fclose(fp);
457 	  ErrPopUp("LoadGIF: Error writing temp file", "\nBummer!");
458 	  return 0;
459 	}
460 	fclose(fp);
461 	free(pinfo->pic);
462 	pinfo->pic = (byte *) NULL;
463 	if (HasGlobalColormap) {
464 	  memcpy(pinfo->r, r, sizeof r);
465 	  memcpy(pinfo->g, g, sizeof g);
466 	  memcpy(pinfo->b, b, sizeof b);
467 	}
468         BitsPerPixel = GlobalBitsPerPixel;
469         numcols = ColorMapSize = GlobalColorMapSize;
470         BitMask = GlobalBitMask;
471       }
472       if (readImage(pinfo)) ++pinfo->numpages;
473       if (DEBUG) fprintf(stderr, "  at end:   offset=0x%lx\n",
474                          (unsigned long)(dataptr-RawGIF));
475     }
476 
477 
478     else if (block == TRAILER) {      /* stop reading blocks */
479       if (DEBUG) fprintf(stderr,"trailer");
480       break;
481     }
482 
483     else {      /* unknown block type */
484       char str[128];
485 
486       if (DEBUG) fprintf(stderr,"block type 0x%02x  ", block);
487 
488       /* don't mention bad block if file was trunc'd, as it's all bogus */
489       if ((dataptr - origptr) < filesize) {
490 	sprintf(str, "Unknown block type (0x%02x) at offset 0x%lx",
491 		block, (unsigned long)(dataptr - origptr) - 1);
492 
493 	if (!pinfo->numpages) return gifError(pinfo, str);
494 	else gifWarning(str);
495       }
496 
497       break;
498     }
499 
500     if (DEBUG) fprintf(stderr,"\n");
501   }
502 
503   free(RawGIF);	 RawGIF = NULL;
504   free(Raster);  Raster = NULL;
505 
506   if (!pinfo->numpages)
507      return( gifError(pinfo, "no image data found in GIF file") );
508   if (pinfo->numpages > 1) {
509     /* write the last page temp file */
510     int numpages = pinfo->numpages;
511     char *comment = pinfo->comment;
512     sprintf(tmpname, "%s%d", pinfo->pagebname, pinfo->numpages);
513     fp = xv_fopen(tmpname, "w");
514     if (!fp) {
515       ErrPopUp("LoadGIF: Unable to open temp file", "\nDang!");
516       return 0;
517     }
518     if (WriteGIF(fp, pinfo->pic, pinfo->type, pinfo->w, pinfo->h, pinfo->r,
519 		 pinfo->g, pinfo->b, numcols, pinfo->colType, NULL)) {
520       fclose(fp);
521       ErrPopUp("LoadGIF: Error writing temp file", "\nBummer!");
522       return 0;
523     }
524     fclose(fp);
525     free(pinfo->pic);
526     pinfo->pic = (byte *) NULL;
527 
528     /* load the first page temp file */
529     sprintf(tmpname, "%s%d", pinfo->pagebname, 1);
530     i = LoadGIF(tmpname, pinfo);
531     pinfo->numpages = numpages;
532     pinfo->comment = comment;
533   }
534 
535   return 1;
536 }
537 
538 
539 /********************************************/
readImage(pinfo)540 static int readImage(pinfo)
541      PICINFO *pinfo;
542 {
543   register byte ch, ch1, *ptr1, *picptr;
544   int           i, npixels, maxpixels;
545   boolean       HasLocalColormap;
546 
547   npixels = maxpixels = 0;
548 
549   /* read in values from the image descriptor */
550 
551   ch = NEXTBYTE;
552   LeftOfs = ch + 0x100 * NEXTBYTE;
553   ch = NEXTBYTE;
554   TopOfs  = ch + 0x100 * NEXTBYTE;
555   ch = NEXTBYTE;
556   Width   = ch + 0x100 * NEXTBYTE;
557   ch = NEXTBYTE;
558   Height  = ch + 0x100 * NEXTBYTE;
559 
560   Misc = NEXTBYTE;
561   Interlace = ((Misc & INTERLACEMASK) ? True : False);
562   HasLocalColormap = ((Misc & COLORMAPMASK) ? True : False);
563 
564   if (HasLocalColormap) {
565     BitsPerPixel = (Misc & 7) + 1;
566     ColorMapSize = numcols = 1 << BitsPerPixel;  /* GRR 20070318 */
567     BitMask = ColorMapSize - 1;
568     if (DEBUG) fprintf(stderr,"  local color table, %d bits (%d entries)\n",
569       (Misc&7)+1, ColorMapSize);
570     for (i=0; i<ColorMapSize; i++) {
571       pinfo->r[i] = NEXTBYTE;
572       pinfo->g[i] = NEXTBYTE;
573       pinfo->b[i] = NEXTBYTE;
574     }
575     if (DEBUG > 1) {
576       for (i=0; i<ColorMapSize; i++) {
577         fprintf(stderr,"    (%3d  %02x,%02x,%02x)\n", i, pinfo->r[i],
578           pinfo->g[i], pinfo->b[i]);
579       }
580     }
581   }
582 
583 
584   if (!HasGlobalColormap && !HasLocalColormap) {
585     /* no global or local colormap */
586     SetISTR(ISTR_WARNING, "%s:  %s", bname,
587 	    "No colormap in this GIF file.  Assuming EGA colors.");
588   }
589 
590 
591   /* GRR 19980314 */
592   /* need not worry about size of EGA palette:  full 256 colors */
593   if (have_imagebg && Transparent >= 0 &&
594       Transparent < ((Misc&0x80)? (1 << ((Misc&7)+1)) : ColorMapSize) )
595   {
596     pinfo->r[Transparent] = (imagebgR >> 8);
597     pinfo->g[Transparent] = (imagebgG >> 8);
598     pinfo->b[Transparent] = (imagebgB >> 8);
599   }
600 
601 
602 
603   /* Start reading the raster data. First we get the intial code size
604    * and compute decompressor constant values, based on this code size.
605    */
606 
607   CodeSize = NEXTBYTE;
608 
609   ClearCode = (1 << CodeSize);
610   EOFCode = ClearCode + 1;
611   FreeCode = FirstFree = ClearCode + 2;
612 
613   /* The GIF spec has it that the code size is the code size used to
614    * compute the above values is the code size given in the file, but the
615    * code size used in compression/decompression is the code size given in
616    * the file plus one. (thus the ++).
617    */
618 
619   CodeSize++;
620   InitCodeSize = CodeSize;
621   MaxCode = (1 << CodeSize);
622   ReadMask = MaxCode - 1;
623 
624 
625 
626   /* UNBLOCK:
627    * Read the raster data.  Here we just transpose it from the GIF array
628    * to the Raster array, turning it from a series of blocks into one long
629    * data stream, which makes life much easier for readCode().
630    */
631 
632   ptr1 = Raster;
633   do {
634     ch = ch1 = NEXTBYTE;
635     while (ch--) { *ptr1 = NEXTBYTE; ptr1++; }
636     if ((dataptr - RawGIF) > filesize) {
637       SetISTR(ISTR_WARNING,"%s:  %s", bname,
638 	      "This GIF file seems to be truncated.  Winging it.");
639       break;
640     }
641   } while(ch1);
642 
643 
644 
645 
646   if (DEBUG) {
647     fprintf(stderr,"LoadGIF: image is %dx%d, %d bits, %sinterlaced\n",
648 	    Width, Height, BitsPerPixel, Interlace ? "" : "non-");
649   }
650 
651 
652   /* Allocate the 'pic' */
653   maxpixels = Width*Height;  /* 65535*65535 max (but everything is int) */
654   if (Width <= 0 || Height <= 0 || maxpixels/Width != Height)
655     return( gifError(pinfo, "image dimensions out of range") );
656   picptr = pic8 = (byte *) malloc((size_t) maxpixels);
657   if (!pic8) FatalError("LoadGIF: couldn't malloc 'pic8'");
658 
659 
660 
661   /* Decompress the file, continuing until you see the GIF EOF code.
662    * One obvious enhancement is to add checking for corrupt files here.
663    */
664 
665   Code = readCode();
666   while (Code != EOFCode) {
667     /* Clear code sets everything back to its initial value, then reads the
668      * immediately subsequent code as uncompressed data.
669      */
670 
671     if (Code == ClearCode) {
672       CodeSize = InitCodeSize;
673       MaxCode = (1 << CodeSize);
674       ReadMask = MaxCode - 1;
675       FreeCode = FirstFree;
676       Code = readCode();
677       CurCode = OldCode = Code;
678       FinChar = CurCode & BitMask;
679       if (!Interlace) *picptr++ = FinChar;
680          else doInterlace(FinChar);
681       npixels++;
682     }
683     else {
684       /* If not a clear code, must be data: save same as CurCode and InCode */
685 
686       /* if we're at maxcode and didn't get a clear, stop loading */
687       if (FreeCode>=4096) { /* printf("freecode blew up\n"); */
688 			    break; }
689 
690       CurCode = InCode = Code;
691 
692       /* If greater or equal to FreeCode, not in the hash table yet;
693        * repeat the last character decoded
694        */
695 
696       if (CurCode >= FreeCode) {
697 	CurCode = OldCode;
698 	if (OutCount > 4096) {  /* printf("outcount1 blew up\n"); */ break; }
699 	OutCode[OutCount++] = FinChar;
700       }
701 
702       /* Unless this code is raw data, pursue the chain pointed to by CurCode
703        * through the hash table to its end; each code in the chain puts its
704        * associated output code on the output queue.
705        */
706 
707       while (CurCode >= ClearCode) {  /* Joe Zbiciak fix, 20070621 */
708 	if (OutCount > 4096) break;   /* corrupt file */
709 	OutCode[OutCount++] = Suffix[CurCode];
710 	CurCode = Prefix[CurCode];
711       }
712 
713       if (OutCount > 4096) { /* printf("outcount blew up\n"); */ break; }
714 
715       /* The last code in the chain is treated as raw data. */
716 
717       FinChar = CurCode & BitMask;
718       OutCode[OutCount++] = FinChar;
719 
720       /* Now we put the data out to the Output routine.
721        * It's been stacked LIFO, so deal with it that way...
722        */
723 
724       /* safety thing:  prevent exceeding range of 'pic8' */
725       if (npixels + OutCount > maxpixels) OutCount = maxpixels-npixels;
726 
727       npixels += OutCount;
728       if (!Interlace) for (i=OutCount-1; i>=0; i--) *picptr++ = OutCode[i];
729                 else  for (i=OutCount-1; i>=0; i--) doInterlace(OutCode[i]);
730       OutCount = 0;
731 
732       /* Build the hash table on-the-fly. No table is stored in the file. */
733 
734       Prefix[FreeCode] = OldCode;
735       Suffix[FreeCode] = FinChar;
736       OldCode = InCode;
737 
738       /* Point to the next slot in the table.  If we exceed the current
739        * MaxCode value, increment the code size unless it's already 12.  If it
740        * is, do nothing: the next code decompressed better be CLEAR
741        */
742 
743       FreeCode++;
744       if (FreeCode >= MaxCode) {
745 	if (CodeSize < 12) {
746 	  CodeSize++;
747 	  MaxCode *= 2;
748 	  ReadMask = (1 << CodeSize) - 1;
749 	}
750       }
751     }
752     Code = readCode();
753     if (npixels >= maxpixels) break;
754   }
755 
756   if (npixels != maxpixels) {
757     SetISTR(ISTR_WARNING,"%s:  %s", bname,
758 	    "This GIF file seems to be truncated.  Winging it.");
759     if (!Interlace)  /* clear->EOBuffer */
760       xvbzero((char *) pic8+npixels,
761 	      (size_t) (maxpixels-npixels<0 ? 0 : maxpixels-npixels));
762   }
763 
764   /* fill in the PICINFO structure */
765 
766   pinfo->pic     = pic8;
767   pinfo->w       = Width;
768   pinfo->h       = Height;
769   pinfo->type    = PIC8;
770   pinfo->frmType = F_GIF;
771   pinfo->colType = F_FULLCOLOR;
772 
773   pinfo->normw = pinfo->w;   pinfo->normh = pinfo->h;
774 
775   sprintf(pinfo->fullInfo,
776 	  "GIF%s, %d bit%s per pixel, %sinterlaced.  (%d bytes)",
777  	  (gif89) ? "89" : "87", BitsPerPixel,
778 	  (BitsPerPixel==1) ? "" : "s",
779  	  Interlace ? "" : "non-", filesize);
780 
781   sprintf(pinfo->shrtInfo, "%dx%d GIF%s.",Width,Height,(gif89) ? "89" : "87");
782 
783   /* pinfo.comment gets handled in main LoadGIF() block-reader */
784 
785   return 1;
786 }
787 
788 
789 
790 /* Fetch the next code from the raster data stream.  The codes can be
791  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
792  * maintain our location in the Raster array as a BIT Offset.  We compute
793  * the byte Offset into the raster array by dividing this by 8, pick up
794  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
795  * bring the desired code to the bottom, then mask it off and return it.
796  */
797 
readCode()798 static int readCode()
799 {
800   int RawCode, ByteOffset;
801 
802   ByteOffset = BitOffset / 8;
803   RawCode = Raster[ByteOffset] + (Raster[ByteOffset + 1] << 8);
804   if (CodeSize >= 8)
805     RawCode += ( ((int) Raster[ByteOffset + 2]) << 16);
806   RawCode >>= (BitOffset % 8);
807   BitOffset += CodeSize;
808 
809   return(RawCode & ReadMask);
810 }
811 
812 
813 /***************************/
doInterlace(Index)814 static void doInterlace(Index)
815      int Index;
816 {
817   static byte *ptr = NULL;
818   static int   oldYC = -1;
819 
820   if (Pass == -1) {  /* first time through - init stuff */
821     oldYC = -1;
822     Pass = 0;
823   }
824 
825   if (oldYC != YC) {  ptr = pic8 + YC * Width;  oldYC = YC; }
826 
827   if (YC<Height)
828     *ptr++ = Index;
829 
830   /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
831 
832   if (++XC == Width) {
833 
834     /* deal with the interlace as described in the GIF
835      * spec.  Put the decoded scan line out to the screen if we haven't gone
836      * past the bottom of it
837      */
838 
839     XC = 0;
840 
841     switch (Pass) {
842     case 0:
843       YC += 8;
844       if (YC >= Height) { Pass++; YC = 4; }
845       break;
846 
847     case 1:
848       YC += 8;
849       if (YC >= Height) { Pass++; YC = 2; }
850       break;
851 
852     case 2:
853       YC += 4;
854       if (YC >= Height) { Pass++; YC = 1; }
855       break;
856 
857     case 3:
858       YC += 2;  break;
859 
860     default:
861       break;
862     }
863   }
864 }
865 
866 
867 
868 /*****************************/
gifError(pinfo,st)869 static int gifError(pinfo, st)
870      PICINFO    *pinfo;
871      const char *st;
872 {
873   gifWarning(st);
874 
875   if (RawGIF != NULL) free(RawGIF);
876   if (Raster != NULL) free(Raster);
877 
878   if (pinfo->pic) free(pinfo->pic);
879   if (pinfo->comment) free(pinfo->comment);
880 
881   if (pic8 && pic8 != pinfo->pic) free(pic8);
882 
883   pinfo->pic = (byte *) NULL;
884   pinfo->comment = (char *) NULL;
885 
886   return 0;
887 }
888 
889 
890 /*****************************/
gifWarning(st)891 static void gifWarning(st)
892      const char *st;
893 {
894   SetISTR(ISTR_WARNING,"%s:  %s", bname, st);
895 }
896 
897 
898