2 * "$Id: image-gif.c 9865 2011-08-06 04:38:04Z mike $"
4 * GIF image routines for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * _cupsImageReadGIF() - Read a GIF image file.
20 * gif_get_block() - Read a GIF data block...
21 * gif_get_code() - Get a LZW code from the file...
22 * gif_read_cmap() - Read the colormap from a GIF file...
23 * gif_read_image() - Read a GIF image stream...
24 * gif_read_lzw() - Read a byte from the LZW stream...
28 * Include necessary headers...
31 #include "image-private.h"
38 #define GIF_INTERLACE 0x40
39 #define GIF_COLORMAP 0x80
40 #define GIF_MAX_BITS 12
42 typedef cups_ib_t gif_cmap_t[256][4];
43 typedef short gif_table_t[4096];
50 static int gif_eof = 0; /* Did we hit EOF? */
57 static int gif_get_block(FILE *fp, unsigned char *buffer);
58 static int gif_get_code (FILE *fp, int code_size, int first_time);
59 static int gif_read_cmap(FILE *fp, int ncolors, gif_cmap_t cmap,
61 static int gif_read_image(FILE *fp, cups_image_t *img, gif_cmap_t cmap,
63 static int gif_read_lzw(FILE *fp, int first_time, int input_code_size);
67 * '_cupsImageReadGIF()' - Read a GIF image file.
70 int /* O - Read status */
72 cups_image_t *img, /* IO - cupsImage */
73 FILE *fp, /* I - cupsImage file */
74 cups_icspace_t primary, /* I - Primary choice for colorspace */
75 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
76 int saturation, /* I - Color saturation (%) */
77 int hue, /* I - Color hue (degrees) */
78 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
80 unsigned char buf[1024]; /* Input buffer */
81 gif_cmap_t cmap; /* Colormap */
82 int i, /* Looping var */
83 bpp, /* Bytes per pixel */
84 gray, /* Grayscale image? */
85 ncolors, /* Bits per pixel */
86 transparent; /* Transparent color index */
90 * GIF files are either grayscale or RGB - no CMYK...
93 if (primary == CUPS_IMAGE_RGB_CMYK)
94 primary = CUPS_IMAGE_RGB;
97 * Read the header; we already know it is a GIF file...
100 fread(buf, 13, 1, fp);
102 img->xsize = (buf[7] << 8) | buf[6];
103 img->ysize = (buf[9] << 8) | buf[8];
104 ncolors = 2 << (buf[10] & 0x07);
105 gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
107 if (buf[10] & GIF_COLORMAP)
108 if (gif_read_cmap(fp, ncolors, cmap, &gray))
120 case ';' : /* End of image */
122 return (-1); /* Early end of file */
124 case '!' : /* Extension record */
126 if (buf[0] == 0xf9) /* Graphic Control Extension */
128 gif_get_block(fp, buf);
129 if (buf[0] & 1) /* Get transparent color index */
130 transparent = buf[3];
133 while (gif_get_block(fp, buf) != 0);
136 case ',' : /* cupsImage data */
137 fread(buf, 9, 1, fp);
139 if (buf[8] & GIF_COLORMAP)
141 ncolors = 2 << (buf[8] & 0x07);
142 gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
144 if (gif_read_cmap(fp, ncolors, cmap, &gray))
151 if (transparent >= 0)
154 * Make transparent color white...
157 cmap[transparent][0] = 255;
158 cmap[transparent][1] = 255;
159 cmap[transparent][2] = 255;
166 case CUPS_IMAGE_CMYK :
167 for (i = ncolors - 1; i >= 0; i --)
168 cupsImageWhiteToCMYK(cmap[i], cmap[i], 1);
170 case CUPS_IMAGE_CMY :
171 for (i = ncolors - 1; i >= 0; i --)
172 cupsImageWhiteToCMY(cmap[i], cmap[i], 1);
174 case CUPS_IMAGE_BLACK :
175 for (i = ncolors - 1; i >= 0; i --)
176 cupsImageWhiteToBlack(cmap[i], cmap[i], 1);
178 case CUPS_IMAGE_WHITE :
180 case CUPS_IMAGE_RGB :
181 case CUPS_IMAGE_RGB_CMYK :
182 for (i = ncolors - 1; i >= 0; i --)
183 cupsImageWhiteToRGB(cmap[i], cmap[i], 1);
187 img->colorspace = secondary;
191 if (hue != 0 || saturation != 100)
192 for (i = ncolors - 1; i >= 0; i --)
193 cupsImageRGBAdjust(cmap[i], 1, saturation, hue);
197 case CUPS_IMAGE_CMYK :
198 for (i = ncolors - 1; i >= 0; i --)
199 cupsImageRGBToCMYK(cmap[i], cmap[i], 1);
201 case CUPS_IMAGE_CMY :
202 for (i = ncolors - 1; i >= 0; i --)
203 cupsImageRGBToCMY(cmap[i], cmap[i], 1);
205 case CUPS_IMAGE_BLACK :
206 for (i = ncolors - 1; i >= 0; i --)
207 cupsImageRGBToBlack(cmap[i], cmap[i], 1);
209 case CUPS_IMAGE_WHITE :
210 for (i = ncolors - 1; i >= 0; i --)
211 cupsImageRGBToWhite(cmap[i], cmap[i], 1);
213 case CUPS_IMAGE_RGB :
214 case CUPS_IMAGE_RGB_CMYK :
215 for (i = ncolors - 1; i >= 0; i --)
216 cupsImageRGBToRGB(cmap[i], cmap[i], 1);
220 img->colorspace = primary;
225 bpp = cupsImageGetDepth(img);
227 for (i = ncolors - 1; i >= 0; i --)
228 cupsImageLut(cmap[i], bpp, lut);
231 img->xsize = (buf[5] << 8) | buf[4];
232 img->ysize = (buf[7] << 8) | buf[6];
235 * Check the dimensions of the image; since the dimensions are
236 * a 16-bit integer we just need to check for 0...
239 if (img->xsize == 0 || img->ysize == 0)
241 fprintf(stderr, "DEBUG: Bad GIF image dimensions: %dx%d\n",
242 img->xsize, img->ysize);
247 i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE);
256 * 'gif_get_block()' - Read a GIF data block...
259 static int /* O - Number characters read */
260 gif_get_block(FILE *fp, /* I - File to read from */
261 unsigned char *buf) /* I - Input buffer */
263 int count; /* Number of character to read */
267 * Read the count byte followed by the data from the file...
270 if ((count = getc(fp)) == EOF)
277 else if (fread(buf, 1, count, fp) < count)
290 * 'gif_get_code()' - Get a LZW code from the file...
293 static int /* O - LZW code */
294 gif_get_code(FILE *fp, /* I - File to read from */
295 int code_size, /* I - Size of code in bits */
296 int first_time) /* I - 1 = first time, 0 = not first time */
298 unsigned i, j, /* Looping vars */
299 ret; /* Return value */
300 int count; /* Number of bytes read */
301 static unsigned char buf[280]; /* Input buffer */
302 static unsigned curbit, /* Current bit */
303 lastbit, /* Last bit in buffer */
304 done, /* Done with this buffer? */
305 last_byte; /* Last byte in buffer */
306 static const unsigned char bits[8] = /* Bit masks for codes */
308 0x01, 0x02, 0x04, 0x08,
309 0x10, 0x20, 0x40, 0x80
316 * Just initialize the input buffer...
327 if ((curbit + code_size) >= lastbit)
330 * Don't have enough bits to hold the code...
334 return (-1); /* Sorry, no more... */
337 * Move last two bytes to front of buffer...
342 buf[0] = buf[last_byte - 2];
343 buf[1] = buf[last_byte - 1];
346 else if (last_byte == 1)
348 buf[0] = buf[last_byte - 1];
353 * Read in another buffer...
356 if ((count = gif_get_block(fp, buf + last_byte)) <= 0)
359 * Whoops, no more data!
367 * Update buffer state...
370 curbit = (curbit - lastbit) + 8 * last_byte;
372 lastbit = last_byte * 8;
375 for (ret = 0, i = curbit + code_size - 1, j = code_size;
378 ret = (ret << 1) | ((buf[i / 8] & bits[i & 7]) != 0);
387 * 'gif_read_cmap()' - Read the colormap from a GIF file...
390 static int /* O - -1 on error, 0 on success */
391 gif_read_cmap(FILE *fp, /* I - File to read from */
392 int ncolors, /* I - Number of colors in file */
393 gif_cmap_t cmap, /* O - Colormap information */
394 int *gray) /* IO - Is the image grayscale? */
396 int i; /* Looping var */
400 * Read the colormap...
403 for (i = 0; i < ncolors; i ++)
404 if (fread(cmap[i], 3, 1, fp) < 1)
408 * Check to see if the colormap is a grayscale ramp...
411 for (i = 0; i < ncolors; i ++)
412 if (cmap[i][0] != cmap[i][1] || cmap[i][1] != cmap[i][2])
422 * If this needs to be a grayscale image, convert the RGB values to
423 * luminance values...
427 for (i = 0; i < ncolors; i ++)
428 cmap[i][0] = (cmap[i][0] * 31 + cmap[i][1] * 61 + cmap[i][2] * 8) / 100;
435 * 'gif_read_image()' - Read a GIF image stream...
438 static int /* I - 0 = success, -1 = failure */
439 gif_read_image(FILE *fp, /* I - Input file */
440 cups_image_t *img, /* I - cupsImage pointer */
441 gif_cmap_t cmap, /* I - Colormap */
442 int interlace) /* I - Non-zero = interlaced image */
444 unsigned char code_size; /* Code size */
445 cups_ib_t *pixels, /* Pixel buffer */
446 *temp; /* Current pixel */
447 int xpos, /* Current X position */
448 ypos, /* Current Y position */
449 pass; /* Current pass */
450 int pixel; /* Current pixel */
451 int bpp; /* Bytes per pixel */
452 static const int xpasses[4] = /* X interleaving */
454 ypasses[5] = /* Y interleaving */
455 { 0, 4, 2, 1, 999999 };
458 bpp = cupsImageGetDepth(img);
459 pixels = calloc(bpp, img->xsize);
463 code_size = getc(fp);
468 if (code_size > GIF_MAX_BITS || gif_read_lzw(fp, 1, code_size) < 0)
475 while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0)
480 temp[3] = cmap[pixel][3];
482 temp[2] = cmap[pixel][2];
484 temp[1] = cmap[pixel][1];
486 temp[0] = cmap[pixel][0];
491 if (xpos == img->xsize)
493 _cupsImagePutRow(img, 0, ypos, img->xsize, pixels);
500 ypos += xpasses[pass];
502 if (ypos >= img->ysize)
506 ypos = ypasses[pass];
513 if (ypos >= img->ysize)
524 * 'gif_read_lzw()' - Read a byte from the LZW stream...
527 static int /* I - Byte from stream */
528 gif_read_lzw(FILE *fp, /* I - File to read from */
529 int first_time, /* I - 1 = first time, 0 = not first time */
530 int input_code_size) /* I - Code size in bits */
532 int i, /* Looping var */
533 code, /* Current code */
534 incode; /* Input code */
535 static short fresh = 0, /* 1 = empty buffers */
536 code_size, /* Current code size */
537 set_code_size, /* Initial code size set */
538 max_code, /* Maximum code used */
539 max_code_size, /* Maximum code size */
540 firstcode, /* First code read */
541 oldcode, /* Last code read */
542 clear_code, /* Clear code for LZW input */
543 end_code, /* End code for LZW input */
544 *stack = NULL, /* Output stack */
545 *sp; /* Current stack pointer */
546 static gif_table_t *table = NULL; /* String table */
555 set_code_size = input_code_size;
556 code_size = set_code_size + 1;
557 clear_code = 1 << set_code_size;
558 end_code = clear_code + 1;
559 max_code_size = 2 * clear_code;
560 max_code = clear_code + 2;
563 * Allocate memory for buffers...
567 table = calloc(2, sizeof(gif_table_t));
573 stack = calloc(8192, sizeof(short));
579 * Initialize input buffers...
582 gif_get_code(fp, 0, 1);
585 * Wipe the decompressor table (already mostly 0 due to the calloc above...)
590 for (i = 1; i < clear_code; i ++)
603 firstcode = oldcode = gif_get_code(fp, code_size, 0);
605 while (firstcode == clear_code);
607 return (firstcode & 255);
613 return ((*--sp) & 255);
615 while ((code = gif_get_code(fp, code_size, 0)) >= 0)
617 if (code == clear_code)
620 * Clear/reset the compression table...
623 memset(table, 0, 2 * sizeof(gif_table_t));
624 for (i = 1; i < clear_code; i ++)
627 code_size = set_code_size + 1;
628 max_code_size = 2 * clear_code;
629 max_code = clear_code + 2;
633 firstcode = oldcode = gif_get_code(fp, code_size, 0);
635 return (firstcode & 255);
637 else if (code == end_code || code > max_code)
639 unsigned char buf[260]; /* Block buffer */
642 while (gif_get_block(fp, buf) > 0);
649 if (code == max_code)
651 if (sp < (stack + 8192))
657 while (code >= clear_code && sp < (stack + 8192))
659 *sp++ = table[1][code];
660 if (code == table[0][code])
663 code = table[0][code];
666 if (sp < (stack + 8192))
667 *sp++ = firstcode = table[1][code];
673 table[0][code] = oldcode;
674 table[1][code] = firstcode;
677 if (max_code >= max_code_size && max_code_size < 4096)
687 return ((*--sp) & 255);
695 * End of "$Id: image-gif.c 9865 2011-08-06 04:38:04Z mike $".