]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-gif.c
2 * "$Id: image-gif.c 7720 2008-07-11 22:46:21Z 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 7720 2008-07-11 22:46:21Z mike $".