]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-gif.c
2 * "$Id: image-gif.c 6649 2007-07-11 21:46:42Z mike $"
4 * GIF image routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007 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
41 typedef cups_ib_t gif_cmap_t
[256][4];
42 typedef short gif_table_t
[4096];
49 static int gif_eof
= 0; /* Did we hit EOF? */
56 static int gif_get_block(FILE *fp
, unsigned char *buffer
);
57 static int gif_get_code (FILE *fp
, int code_size
, int first_time
);
58 static int gif_read_cmap(FILE *fp
, int ncolors
, gif_cmap_t cmap
,
60 static int gif_read_image(FILE *fp
, cups_image_t
*img
, gif_cmap_t cmap
,
62 static int gif_read_lzw(FILE *fp
, int first_time
, int input_code_size
);
66 * '_cupsImageReadGIF()' - Read a GIF image file.
69 int /* O - Read status */
71 cups_image_t
*img
, /* IO - cupsImage */
72 FILE *fp
, /* I - cupsImage file */
73 cups_icspace_t primary
, /* I - Primary choice for colorspace */
74 cups_icspace_t secondary
, /* I - Secondary choice for colorspace */
75 int saturation
, /* I - Color saturation (%) */
76 int hue
, /* I - Color hue (degrees) */
77 const cups_ib_t
*lut
) /* I - Lookup table for gamma/brightness */
79 unsigned char buf
[1024]; /* Input buffer */
80 gif_cmap_t cmap
; /* Colormap */
81 int i
, /* Looping var */
82 bpp
, /* Bytes per pixel */
83 gray
, /* Grayscale image? */
84 ncolors
, /* Bits per pixel */
85 transparent
; /* Transparent color index */
89 * GIF files are either grayscale or RGB - no CMYK...
92 if (primary
== CUPS_IMAGE_RGB_CMYK
)
93 primary
= CUPS_IMAGE_RGB
;
96 * Read the header; we already know it is a GIF file...
99 fread(buf
, 13, 1, fp
);
101 img
->xsize
= (buf
[7] << 8) | buf
[6];
102 img
->ysize
= (buf
[9] << 8) | buf
[8];
103 ncolors
= 2 << (buf
[10] & 0x07);
104 gray
= primary
== CUPS_IMAGE_BLACK
|| primary
== CUPS_IMAGE_WHITE
;
106 if (buf
[10] & GIF_COLORMAP
)
107 if (gif_read_cmap(fp
, ncolors
, cmap
, &gray
))
119 case ';' : /* End of image */
121 return (-1); /* Early end of file */
123 case '!' : /* Extension record */
125 if (buf
[0] == 0xf9) /* Graphic Control Extension */
127 gif_get_block(fp
, buf
);
128 if (buf
[0] & 1) /* Get transparent color index */
129 transparent
= buf
[3];
132 while (gif_get_block(fp
, buf
) != 0);
135 case ',' : /* cupsImage data */
136 fread(buf
, 9, 1, fp
);
138 if (buf
[8] & GIF_COLORMAP
)
140 ncolors
= 2 << (buf
[8] & 0x07);
141 gray
= primary
== CUPS_IMAGE_BLACK
|| primary
== CUPS_IMAGE_WHITE
;
143 if (gif_read_cmap(fp
, ncolors
, cmap
, &gray
))
150 if (transparent
>= 0)
153 * Make transparent color white...
156 cmap
[transparent
][0] = 255;
157 cmap
[transparent
][1] = 255;
158 cmap
[transparent
][2] = 255;
165 case CUPS_IMAGE_CMYK
:
166 for (i
= ncolors
- 1; i
>= 0; i
--)
167 cupsImageWhiteToCMYK(cmap
[i
], cmap
[i
], 1);
169 case CUPS_IMAGE_CMY
:
170 for (i
= ncolors
- 1; i
>= 0; i
--)
171 cupsImageWhiteToCMY(cmap
[i
], cmap
[i
], 1);
173 case CUPS_IMAGE_BLACK
:
174 for (i
= ncolors
- 1; i
>= 0; i
--)
175 cupsImageWhiteToBlack(cmap
[i
], cmap
[i
], 1);
177 case CUPS_IMAGE_WHITE
:
179 case CUPS_IMAGE_RGB
:
180 case CUPS_IMAGE_RGB_CMYK
:
181 for (i
= ncolors
- 1; i
>= 0; i
--)
182 cupsImageWhiteToRGB(cmap
[i
], cmap
[i
], 1);
186 img
->colorspace
= secondary
;
190 if (hue
!= 0 || saturation
!= 100)
191 for (i
= ncolors
- 1; i
>= 0; i
--)
192 cupsImageRGBAdjust(cmap
[i
], 1, saturation
, hue
);
196 case CUPS_IMAGE_CMYK
:
197 for (i
= ncolors
- 1; i
>= 0; i
--)
198 cupsImageRGBToCMYK(cmap
[i
], cmap
[i
], 1);
200 case CUPS_IMAGE_CMY
:
201 for (i
= ncolors
- 1; i
>= 0; i
--)
202 cupsImageRGBToCMY(cmap
[i
], cmap
[i
], 1);
204 case CUPS_IMAGE_BLACK
:
205 for (i
= ncolors
- 1; i
>= 0; i
--)
206 cupsImageRGBToBlack(cmap
[i
], cmap
[i
], 1);
208 case CUPS_IMAGE_WHITE
:
209 for (i
= ncolors
- 1; i
>= 0; i
--)
210 cupsImageRGBToWhite(cmap
[i
], cmap
[i
], 1);
212 case CUPS_IMAGE_RGB
:
213 case CUPS_IMAGE_RGB_CMYK
:
214 for (i
= ncolors
- 1; i
>= 0; i
--)
215 cupsImageRGBToRGB(cmap
[i
], cmap
[i
], 1);
219 img
->colorspace
= primary
;
224 bpp
= cupsImageGetDepth(img
);
226 for (i
= ncolors
- 1; i
>= 0; i
--)
227 cupsImageLut(cmap
[i
], bpp
, lut
);
230 img
->xsize
= (buf
[5] << 8) | buf
[4];
231 img
->ysize
= (buf
[7] << 8) | buf
[6];
234 * Check the dimensions of the image; since the dimensions are
235 * a 16-bit integer we just need to check for 0...
238 if (img
->xsize
== 0 || img
->ysize
== 0)
240 fprintf(stderr
, "DEBUG: Bad GIF image dimensions: %dx%d\n",
241 img
->xsize
, img
->ysize
);
246 i
= gif_read_image(fp
, img
, cmap
, buf
[8] & GIF_INTERLACE
);
255 * 'gif_get_block()' - Read a GIF data block...
258 static int /* O - Number characters read */
259 gif_get_block(FILE *fp
, /* I - File to read from */
260 unsigned char *buf
) /* I - Input buffer */
262 int count
; /* Number of character to read */
266 * Read the count byte followed by the data from the file...
269 if ((count
= getc(fp
)) == EOF
)
276 else if (fread(buf
, 1, count
, fp
) < count
)
289 * 'gif_get_code()' - Get a LZW code from the file...
292 static int /* O - LZW code */
293 gif_get_code(FILE *fp
, /* I - File to read from */
294 int code_size
, /* I - Size of code in bits */
295 int first_time
) /* I - 1 = first time, 0 = not first time */
297 unsigned i
, j
, /* Looping vars */
298 ret
; /* Return value */
299 int count
; /* Number of bytes read */
300 static unsigned char buf
[280]; /* Input buffer */
301 static unsigned curbit
, /* Current bit */
302 lastbit
, /* Last bit in buffer */
303 done
, /* Done with this buffer? */
304 last_byte
; /* Last byte in buffer */
305 static const unsigned char bits
[8] = /* Bit masks for codes */
307 0x01, 0x02, 0x04, 0x08,
308 0x10, 0x20, 0x40, 0x80
315 * Just initialize the input buffer...
326 if ((curbit
+ code_size
) >= lastbit
)
329 * Don't have enough bits to hold the code...
333 return (-1); /* Sorry, no more... */
336 * Move last two bytes to front of buffer...
341 buf
[0] = buf
[last_byte
- 2];
342 buf
[1] = buf
[last_byte
- 1];
345 else if (last_byte
== 1)
347 buf
[0] = buf
[last_byte
- 1];
352 * Read in another buffer...
355 if ((count
= gif_get_block (fp
, buf
+ last_byte
)) <= 0)
358 * Whoops, no more data!
366 * Update buffer state...
369 curbit
= (curbit
- lastbit
) + 8 * last_byte
;
371 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
);
465 if (gif_read_lzw(fp
, 1, code_size
) < 0)
469 while ((pixel
= gif_read_lzw(fp
, 0, code_size
)) >= 0)
474 temp
[3] = cmap
[pixel
][3];
476 temp
[2] = cmap
[pixel
][2];
478 temp
[1] = cmap
[pixel
][1];
480 temp
[0] = cmap
[pixel
][0];
485 if (xpos
== img
->xsize
)
487 _cupsImagePutRow(img
, 0, ypos
, img
->xsize
, pixels
);
494 ypos
+= xpasses
[pass
];
496 if (ypos
>= img
->ysize
)
500 ypos
= ypasses
[pass
];
507 if (ypos
>= img
->ysize
)
518 * 'gif_read_lzw()' - Read a byte from the LZW stream...
521 static int /* I - Byte from stream */
522 gif_read_lzw(FILE *fp
, /* I - File to read from */
523 int first_time
, /* I - 1 = first time, 0 = not first time */
524 int input_code_size
) /* I - Code size in bits */
526 int i
, /* Looping var */
527 code
, /* Current code */
528 incode
; /* Input code */
529 static short fresh
= 0, /* 1 = empty buffers */
530 code_size
, /* Current code size */
531 set_code_size
, /* Initial code size set */
532 max_code
, /* Maximum code used */
533 max_code_size
, /* Maximum code size */
534 firstcode
, /* First code read */
535 oldcode
, /* Last code read */
536 clear_code
, /* Clear code for LZW input */
537 end_code
, /* End code for LZW input */
538 *stack
= NULL
, /* Output stack */
539 *sp
; /* Current stack pointer */
540 static gif_table_t
*table
= NULL
; /* String table */
549 set_code_size
= input_code_size
;
550 code_size
= set_code_size
+ 1;
551 clear_code
= 1 << set_code_size
;
552 end_code
= clear_code
+ 1;
553 max_code_size
= 2 * clear_code
;
554 max_code
= clear_code
+ 2;
557 * Allocate memory for buffers...
561 table
= calloc(2, sizeof(gif_table_t
));
567 stack
= calloc(8192, sizeof(short));
573 * Initialize input buffers...
576 gif_get_code(fp
, 0, 1);
579 * Wipe the decompressor table...
584 for (i
= 0; i
< clear_code
; i
++)
590 for (; i
< 4096; i
++)
591 table
[0][i
] = table
[1][0] = 0;
602 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
603 while (firstcode
== clear_code
);
611 while ((code
= gif_get_code (fp
, code_size
, 0)) >= 0)
613 if (code
== clear_code
)
615 for (i
= 0; i
< clear_code
; i
++)
621 for (; i
< 4096; i
++)
622 table
[0][i
] = table
[1][i
] = 0;
624 code_size
= set_code_size
+ 1;
625 max_code_size
= 2 * clear_code
;
626 max_code
= clear_code
+ 2;
630 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
634 else if (code
== end_code
)
636 unsigned char buf
[260];
640 while (gif_get_block(fp
, buf
) > 0);
647 if (code
>= max_code
)
653 while (code
>= clear_code
)
655 *sp
++ = table
[1][code
];
656 if (code
== table
[0][code
])
659 code
= table
[0][code
];
662 *sp
++ = firstcode
= table
[1][code
];
667 table
[0][code
] = oldcode
;
668 table
[1][code
] = firstcode
;
671 if (max_code
>= max_code_size
&& max_code_size
< 4096)
689 * End of "$Id: image-gif.c 6649 2007-07-11 21:46:42Z mike $".