• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   GIF image routines for CUPS.
3  *
4  *   Copyright 2007-2011 by Apple Inc.
5  *   Copyright 1993-2007 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   _cupsImageReadGIF() - Read a GIF image file.
15  *   gif_get_block()     - Read a GIF data block...
16  *   gif_get_code()      - Get a LZW code from the file...
17  *   gif_read_cmap()     - Read the colormap from a GIF file...
18  *   gif_read_image()    - Read a GIF image stream...
19  *   gif_read_lzw()      - Read a byte from the LZW stream...
20  */
21 
22 /*
23  * Include necessary headers...
24  */
25 
26 #include "image-private.h"
27 
28 
29 /*
30  * GIF definitions...
31  */
32 
33 #define GIF_INTERLACE	0x40
34 #define GIF_COLORMAP	0x80
35 #define GIF_MAX_BITS	12
36 
37 typedef cups_ib_t	gif_cmap_t[256][4];
38 typedef short		gif_table_t[4096];
39 
40 
41 /*
42  * Local globals...
43  */
44 
45 static int	gif_eof = 0;		/* Did we hit EOF? */
46 
47 
48 /*
49  * Local functions...
50  */
51 
52 static int	gif_get_block(FILE *fp, unsigned char *buffer);
53 static int	gif_get_code (FILE *fp, int code_size, int first_time);
54 static int	gif_read_cmap(FILE *fp, int ncolors, gif_cmap_t cmap,
55 		              int *gray);
56 static int	gif_read_image(FILE *fp, cups_image_t *img, gif_cmap_t cmap,
57 		               int interlace);
58 static int	gif_read_lzw(FILE *fp, int first_time, int input_code_size);
59 
60 
61 /*
62  * '_cupsImageReadGIF()' - Read a GIF image file.
63  */
64 
65 int					/* O - Read status */
_cupsImageReadGIF(cups_image_t * img,FILE * fp,cups_icspace_t primary,cups_icspace_t secondary,int saturation,int hue,const cups_ib_t * lut)66 _cupsImageReadGIF(
67     cups_image_t    *img,		/* IO - cupsImage */
68     FILE            *fp,		/* I - cupsImage file */
69     cups_icspace_t  primary,		/* I - Primary choice for colorspace */
70     cups_icspace_t  secondary,		/* I - Secondary choice for colorspace */
71     int             saturation,		/* I - Color saturation (%) */
72     int             hue,		/* I - Color hue (degrees) */
73     const cups_ib_t *lut)		/* I - Lookup table for gamma/brightness */
74 {
75   unsigned char	buf[1024];		/* Input buffer */
76   gif_cmap_t	cmap;			/* Colormap */
77   int		i,			/* Looping var */
78 		bpp,			/* Bytes per pixel */
79 		gray,			/* Grayscale image? */
80 		ncolors,		/* Bits per pixel */
81 		transparent;		/* Transparent color index */
82 
83 
84  /*
85   * GIF files are either grayscale or RGB - no CMYK...
86   */
87 
88   if (primary == CUPS_IMAGE_RGB_CMYK)
89     primary = CUPS_IMAGE_RGB;
90 
91  /*
92   * Read the header; we already know it is a GIF file...
93   */
94 
95   if (fread(buf, 13, 1, fp) == 0 && ferror(fp))
96     DEBUG_printf(("Error reading file!"));
97 
98   img->xsize = (buf[7] << 8) | buf[6];
99   img->ysize = (buf[9] << 8) | buf[8];
100   ncolors    = 2 << (buf[10] & 0x07);
101   gray       = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
102 
103   if (buf[10] & GIF_COLORMAP)
104     if (gif_read_cmap(fp, ncolors, cmap, &gray))
105     {
106       fclose(fp);
107       return (-1);
108     }
109 
110   transparent = -1;
111 
112   for (;;)
113   {
114     switch (getc(fp))
115     {
116       case ';' :	/* End of image */
117           fclose(fp);
118           return (-1);		/* Early end of file */
119 
120       case '!' :	/* Extension record */
121           buf[0] = getc(fp);
122           if (buf[0] == 0xf9)	/* Graphic Control Extension */
123           {
124             gif_get_block(fp, buf);
125             if (buf[0] & 1)	/* Get transparent color index */
126               transparent = buf[3];
127           }
128 
129           while (gif_get_block(fp, buf) != 0)
130           {
131             if(gif_eof)
132             {
133               return (-1);
134             }
135           }
136           break;
137 
138       case ',' :	/* cupsImage data */
139           if (fread(buf, 9, 1, fp) == 0 && ferror(fp))
140 	    DEBUG_printf(("Error reading file!"));
141 
142           if (buf[8] & GIF_COLORMAP)
143           {
144             ncolors = 2 << (buf[8] & 0x07);
145             gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
146 
147 	    if (gif_read_cmap(fp, ncolors, cmap, &gray))
148 	    {
149               fclose(fp);
150 	      return (-1);
151 	    }
152 	  }
153 
154           if (transparent >= 0)
155           {
156            /*
157             * Make transparent color white...
158             */
159 
160             cmap[transparent][0] = 255;
161             cmap[transparent][1] = 255;
162             cmap[transparent][2] = 255;
163           }
164 
165 	  if (gray)
166 	  {
167 	    switch (secondary)
168 	    {
169               case CUPS_IMAGE_CMYK :
170         	  for (i = ncolors - 1; i >= 0; i --)
171         	    cupsImageWhiteToCMYK(cmap[i], cmap[i], 1);
172         	  break;
173               case CUPS_IMAGE_CMY :
174         	  for (i = ncolors - 1; i >= 0; i --)
175         	    cupsImageWhiteToCMY(cmap[i], cmap[i], 1);
176         	  break;
177               case CUPS_IMAGE_BLACK :
178         	  for (i = ncolors - 1; i >= 0; i --)
179         	    cupsImageWhiteToBlack(cmap[i], cmap[i], 1);
180         	  break;
181               case CUPS_IMAGE_WHITE :
182         	  break;
183               case CUPS_IMAGE_RGB :
184               case CUPS_IMAGE_RGB_CMYK :
185         	  for (i = ncolors - 1; i >= 0; i --)
186         	    cupsImageWhiteToRGB(cmap[i], cmap[i], 1);
187         	  break;
188 	    }
189 
190             img->colorspace = secondary;
191 	  }
192 	  else
193 	  {
194 	    if (hue != 0 || saturation != 100)
195               for (i = ncolors - 1; i >= 0; i --)
196         	cupsImageRGBAdjust(cmap[i], 1, saturation, hue);
197 
198 	    switch (primary)
199 	    {
200               case CUPS_IMAGE_CMYK :
201         	  for (i = ncolors - 1; i >= 0; i --)
202         	    cupsImageRGBToCMYK(cmap[i], cmap[i], 1);
203         	  break;
204               case CUPS_IMAGE_CMY :
205         	  for (i = ncolors - 1; i >= 0; i --)
206         	    cupsImageRGBToCMY(cmap[i], cmap[i], 1);
207         	  break;
208               case CUPS_IMAGE_BLACK :
209         	  for (i = ncolors - 1; i >= 0; i --)
210         	    cupsImageRGBToBlack(cmap[i], cmap[i], 1);
211         	  break;
212               case CUPS_IMAGE_WHITE :
213         	  for (i = ncolors - 1; i >= 0; i --)
214         	    cupsImageRGBToWhite(cmap[i], cmap[i], 1);
215         	  break;
216               case CUPS_IMAGE_RGB :
217               case CUPS_IMAGE_RGB_CMYK :
218         	  for (i = ncolors - 1; i >= 0; i --)
219         	    cupsImageRGBToRGB(cmap[i], cmap[i], 1);
220         	  break;
221 	    }
222 
223             img->colorspace = primary;
224 	  }
225 
226           if (lut)
227 	  {
228 	    bpp = cupsImageGetDepth(img);
229 
230             for (i = ncolors - 1; i >= 0; i --)
231               cupsImageLut(cmap[i], bpp, lut);
232 	  }
233 
234           img->xsize = (buf[5] << 8) | buf[4];
235           img->ysize = (buf[7] << 8) | buf[6];
236 
237          /*
238 	  * Check the dimensions of the image; since the dimensions are
239 	  * a 16-bit integer we just need to check for 0...
240 	  */
241 
242           if (img->xsize == 0 || img->ysize == 0)
243 	  {
244 	    fprintf(stderr, "DEBUG: Bad GIF image dimensions: %dx%d\n",
245 	            img->xsize, img->ysize);
246 	    fclose(fp);
247 	    return (1);
248 	  }
249 
250 	  i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE);
251           fclose(fp);
252           return (i);
253     }
254   }
255 }
256 
257 
258 /*
259  * 'gif_get_block()' - Read a GIF data block...
260  */
261 
262 static int				/* O - Number characters read */
gif_get_block(FILE * fp,unsigned char * buf)263 gif_get_block(FILE          *fp,	/* I - File to read from */
264 	      unsigned char *buf)	/* I - Input buffer */
265 {
266   int	count;				/* Number of character to read */
267 
268 
269  /*
270   * Read the count byte followed by the data from the file...
271   */
272 
273   if ((count = getc(fp)) == EOF)
274   {
275     gif_eof = 1;
276     return (-1);
277   }
278   else if (count == 0)
279     gif_eof = 1;
280   else if (fread(buf, 1, count, fp) < count)
281   {
282     gif_eof = 1;
283     return (-1);
284   }
285   else
286     gif_eof = 0;
287 
288   return (count);
289 }
290 
291 
292 /*
293  * 'gif_get_code()' - Get a LZW code from the file...
294  */
295 
296 static int				/* O - LZW code */
gif_get_code(FILE * fp,int code_size,int first_time)297 gif_get_code(FILE *fp,			/* I - File to read from */
298 	     int  code_size,		/* I - Size of code in bits */
299 	     int  first_time)		/* I - 1 = first time, 0 = not first time */
300 {
301   unsigned		i, j,		/* Looping vars */
302 			ret;		/* Return value */
303   int			count;		/* Number of bytes read */
304   static unsigned char	buf[280];	/* Input buffer */
305   static unsigned	curbit,		/* Current bit */
306 			lastbit,	/* Last bit in buffer */
307 			done,		/* Done with this buffer? */
308 			last_byte;	/* Last byte in buffer */
309   static const unsigned char bits[8] =	/* Bit masks for codes */
310 			{
311 			  0x01, 0x02, 0x04, 0x08,
312 			  0x10, 0x20, 0x40, 0x80
313 			};
314 
315 
316   if (first_time)
317   {
318    /*
319     * Just initialize the input buffer...
320     */
321 
322     curbit    = 0;
323     lastbit   = 0;
324     last_byte = 0;
325     done      = 0;
326 
327     return (0);
328   }
329 
330   if ((curbit + code_size) >= lastbit)
331   {
332    /*
333     * Don't have enough bits to hold the code...
334     */
335 
336     if (done)
337       return (-1);	/* Sorry, no more... */
338 
339    /*
340     * Move last two bytes to front of buffer...
341     */
342 
343     if (last_byte > 1)
344     {
345       buf[0]    = buf[last_byte - 2];
346       buf[1]    = buf[last_byte - 1];
347       last_byte = 2;
348     }
349     else if (last_byte == 1)
350     {
351       buf[0]    = buf[last_byte - 1];
352       last_byte = 1;
353     }
354 
355    /*
356     * Read in another buffer...
357     */
358 
359     if ((count = gif_get_block(fp, buf + last_byte)) <= 0)
360     {
361      /*
362       * Whoops, no more data!
363       */
364 
365       done = 1;
366       return (-1);
367     }
368 
369    /*
370     * Update buffer state...
371     */
372 
373     curbit    = (curbit - lastbit) + 8 * last_byte;
374     last_byte += count;
375     lastbit   = last_byte * 8;
376   }
377 
378   for (ret = 0, i = curbit + code_size - 1, j = code_size;
379        j > 0;
380        i --, j --)
381     ret = (ret << 1) | ((buf[i / 8] & bits[i & 7]) != 0);
382 
383   curbit += code_size;
384 
385   return ret;
386 }
387 
388 
389 /*
390  * 'gif_read_cmap()' - Read the colormap from a GIF file...
391  */
392 
393 static int				/* O - -1 on error, 0 on success */
gif_read_cmap(FILE * fp,int ncolors,gif_cmap_t cmap,int * gray)394 gif_read_cmap(FILE       *fp,		/* I - File to read from */
395   	      int        ncolors,	/* I - Number of colors in file */
396 	      gif_cmap_t cmap,		/* O - Colormap information */
397 	      int        *gray)		/* IO - Is the image grayscale? */
398 {
399   int	i;				/* Looping var */
400 
401 
402  /*
403   * Read the colormap...
404   */
405 
406   for (i = 0; i < ncolors; i ++)
407     if (fread(cmap[i], 3, 1, fp) < 1)
408       return (-1);
409 
410  /*
411   * Check to see if the colormap is a grayscale ramp...
412   */
413 
414   for (i = 0; i < ncolors; i ++)
415     if (cmap[i][0] != cmap[i][1] || cmap[i][1] != cmap[i][2])
416       break;
417 
418   if (i == ncolors)
419   {
420     *gray = 1;
421     return (0);
422   }
423 
424  /*
425   * If this needs to be a grayscale image, convert the RGB values to
426   * luminance values...
427   */
428 
429   if (*gray)
430     for (i = 0; i < ncolors; i ++)
431       cmap[i][0] = (cmap[i][0] * 31 + cmap[i][1] * 61 + cmap[i][2] * 8) / 100;
432 
433   return (0);
434 }
435 
436 
437 /*
438  * 'gif_read_image()' - Read a GIF image stream...
439  */
440 
441 static int				/* I - 0 = success, -1 = failure */
gif_read_image(FILE * fp,cups_image_t * img,gif_cmap_t cmap,int interlace)442 gif_read_image(FILE         *fp,	/* I - Input file */
443 	       cups_image_t *img,	/* I - cupsImage pointer */
444 	       gif_cmap_t   cmap,	/* I - Colormap */
445 	       int          interlace)	/* I - Non-zero = interlaced image */
446 {
447   unsigned char		code_size;	/* Code size */
448   cups_ib_t		*pixels,	/* Pixel buffer */
449 			*temp;		/* Current pixel */
450   int			xpos,		/* Current X position */
451 			ypos,		/* Current Y position */
452 			pass;		/* Current pass */
453   int			pixel;		/* Current pixel */
454   int			bpp;		/* Bytes per pixel */
455   static const int	xpasses[4] =	/* X interleaving */
456 			{ 8, 8, 4, 2 },
457 			ypasses[5] =	/* Y interleaving */
458 			{ 0, 4, 2, 1, 999999 };
459 
460 
461   bpp       = cupsImageGetDepth(img);
462   pixels    = calloc(bpp, img->xsize);
463   xpos      = 0;
464   ypos      = 0;
465   pass      = 0;
466   code_size = getc(fp);
467 
468   if (!pixels)
469     return (-1);
470 
471   if (code_size > GIF_MAX_BITS || gif_read_lzw(fp, 1, code_size) < 0)
472   {
473     free(pixels);
474     return (-1);
475   }
476 
477   temp = pixels;
478   while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0)
479   {
480     switch (bpp)
481     {
482       case 4 :
483           temp[3] = cmap[pixel][3];
484       case 3 :
485           temp[2] = cmap[pixel][2];
486       case 2 :
487           temp[1] = cmap[pixel][1];
488       default :
489           temp[0] = cmap[pixel][0];
490     }
491 
492     xpos ++;
493     temp += bpp;
494     if (xpos == img->xsize)
495     {
496       int res = _cupsImagePutRow(img, 0, ypos, img->xsize, pixels);
497       if(res)
498       {
499         return (-1);
500       }
501       xpos = 0;
502       temp = pixels;
503 
504       if (interlace)
505       {
506         ypos += xpasses[pass];
507 
508         if (ypos >= img->ysize)
509 	{
510 	  pass ++;
511 
512           ypos = ypasses[pass];
513 	}
514       }
515       else
516 	ypos ++;
517     }
518 
519     if (ypos >= img->ysize)
520       break;
521   }
522 
523   free(pixels);
524 
525   return (0);
526 }
527 
528 
529 /*
530  * 'gif_read_lzw()' - Read a byte from the LZW stream...
531  */
532 
533 static int				/* I - Byte from stream */
gif_read_lzw(FILE * fp,int first_time,int input_code_size)534 gif_read_lzw(FILE *fp,			/* I - File to read from */
535 	     int  first_time,		/* I - 1 = first time, 0 = not first time */
536  	     int  input_code_size)	/* I - Code size in bits */
537 {
538   int			i,		/* Looping var */
539 			code,		/* Current code */
540 			incode;		/* Input code */
541   static short		fresh = 0,	/* 1 = empty buffers */
542 			code_size,	/* Current code size */
543 			set_code_size,	/* Initial code size set */
544 			max_code,	/* Maximum code used */
545 			max_code_size,	/* Maximum code size */
546 			firstcode,	/* First code read */
547 			oldcode,	/* Last code read */
548 			clear_code,	/* Clear code for LZW input */
549 			end_code,	/* End code for LZW input */
550 			*stack = NULL,	/* Output stack */
551 			*sp;		/* Current stack pointer */
552   static gif_table_t	*table = NULL;	/* String table */
553 
554 
555   if (first_time)
556   {
557    /*
558     * Setup LZW state...
559     */
560 
561     set_code_size = input_code_size;
562     code_size     = set_code_size + 1;
563     clear_code    = 1 << set_code_size;
564     end_code      = clear_code + 1;
565     max_code_size = 2 * clear_code;
566     max_code      = clear_code + 2;
567 
568    /*
569     * Allocate memory for buffers...
570     */
571 
572     if (table == NULL)
573       table = calloc(2, sizeof(gif_table_t));
574 
575     if (table == NULL)
576       return (-1);
577 
578     if (stack == NULL)
579       stack = calloc(8192, sizeof(short));
580 
581     if (stack == NULL)
582       return (-1);
583 
584    /*
585     * Initialize input buffers...
586     */
587 
588     gif_get_code(fp, 0, 1);
589 
590    /*
591     * Wipe the decompressor table (already mostly 0 due to the calloc above...)
592     */
593 
594     fresh = 1;
595 
596     for (i = 1; i < clear_code; i ++)
597       table[1][i] = i;
598 
599     sp = stack;
600 
601     return (0);
602   }
603   else if (fresh)
604   {
605     fresh = 0;
606 
607     do
608     {
609       firstcode = oldcode = gif_get_code(fp, code_size, 0);
610     }
611     while (firstcode == clear_code);
612 
613     return (firstcode & 255);
614   }
615   else if (!table)
616     return (0);
617 
618   if (sp > stack)
619     return ((*--sp) & 255);
620 
621   while ((code = gif_get_code(fp, code_size, 0)) >= 0)
622   {
623     if (code == clear_code)
624     {
625      /*
626       * Clear/reset the compression table...
627       */
628 
629       memset(table, 0, 2 * sizeof(gif_table_t));
630       for (i = 1; i < clear_code; i ++)
631 	table[1][i] = i;
632 
633       code_size     = set_code_size + 1;
634       max_code_size = 2 * clear_code;
635       max_code      = clear_code + 2;
636 
637       sp = stack;
638 
639       firstcode = oldcode = gif_get_code(fp, code_size, 0);
640 
641       return (firstcode & 255);
642     }
643     else if (code == end_code || code > max_code)
644     {
645       unsigned char	buf[260];	/* Block buffer */
646 
647       if (!gif_eof)
648         while (gif_get_block(fp, buf) > 0);
649 
650       return (-2);
651     }
652 
653     incode = code;
654 
655     if (code == max_code)
656     {
657       if (sp < (stack + 8192))
658 	*sp++ = firstcode;
659 
660       code = oldcode;
661     }
662 
663     while (code >= clear_code && sp < (stack + 8192))
664     {
665       *sp++ = table[1][code];
666       if (code == table[0][code])
667 	return (255);
668 
669       code = table[0][code];
670     }
671 
672     if (sp < (stack + 8192))
673       *sp++ = firstcode = table[1][code];
674 
675     code = max_code;
676 
677     if (code < 4096)
678     {
679       table[0][code] = oldcode;
680       table[1][code] = firstcode;
681       max_code ++;
682 
683       if (max_code >= max_code_size && max_code_size < 4096)
684       {
685 	max_code_size *= 2;
686 	code_size ++;
687       }
688     }
689 
690     oldcode = incode;
691 
692     if (sp > stack)
693       return ((*--sp) & 255);
694   }
695 
696   return (code & 255);
697 }
698 
699