]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-gif.c
2 * "$Id: image-gif.c 177 2006-06-21 00:20:03Z jlovell $"
4 * GIF image routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * _cupsImageReadGIF() - Read a GIF image file.
29 * gif_get_block() - Read a GIF data block...
30 * gif_get_code() - Get a LZW code from the file...
31 * gif_read_cmap() - Read the colormap from a GIF file...
32 * gif_read_image() - Read a GIF image stream...
33 * gif_read_lzw() - Read a byte from the LZW stream...
37 * Include necessary headers...
40 #include "image-private.h"
47 #define GIF_INTERLACE 0x40
48 #define GIF_COLORMAP 0x80
50 typedef cups_ib_t gif_cmap_t
[256][4];
51 typedef short gif_table_t
[4096];
58 static int gif_eof
= 0; /* Did we hit EOF? */
65 static int gif_get_block(FILE *fp
, unsigned char *buffer
);
66 static int gif_get_code (FILE *fp
, int code_size
, int first_time
);
67 static int gif_read_cmap(FILE *fp
, int ncolors
, gif_cmap_t cmap
,
69 static int gif_read_image(FILE *fp
, cups_image_t
*img
, gif_cmap_t cmap
,
71 static int gif_read_lzw(FILE *fp
, int first_time
, int input_code_size
);
75 * '_cupsImageReadGIF()' - Read a GIF image file.
78 int /* O - Read status */
80 cups_image_t
*img
, /* IO - cupsImage */
81 FILE *fp
, /* I - cupsImage file */
82 cups_icspace_t primary
, /* I - Primary choice for colorspace */
83 cups_icspace_t secondary
, /* I - Secondary choice for colorspace */
84 int saturation
, /* I - Color saturation (%) */
85 int hue
, /* I - Color hue (degrees) */
86 const cups_ib_t
*lut
) /* I - Lookup table for gamma/brightness */
88 unsigned char buf
[1024]; /* Input buffer */
89 gif_cmap_t cmap
; /* Colormap */
90 int i
, /* Looping var */
91 bpp
, /* Bytes per pixel */
92 gray
, /* Grayscale image? */
93 ncolors
, /* Bits per pixel */
94 transparent
; /* Transparent color index */
98 * GIF files are either grayscale or RGB - no CMYK...
101 if (primary
== CUPS_IMAGE_RGB_CMYK
)
102 primary
= CUPS_IMAGE_RGB
;
105 * Read the header; we already know it is a GIF file...
108 fread(buf
, 13, 1, fp
);
110 img
->xsize
= (buf
[7] << 8) | buf
[6];
111 img
->ysize
= (buf
[9] << 8) | buf
[8];
112 ncolors
= 2 << (buf
[10] & 0x07);
113 gray
= primary
== CUPS_IMAGE_BLACK
|| primary
== CUPS_IMAGE_WHITE
;
115 if (buf
[10] & GIF_COLORMAP
)
116 if (gif_read_cmap(fp
, ncolors
, cmap
, &gray
))
128 case ';' : /* End of image */
130 return (-1); /* Early end of file */
132 case '!' : /* Extension record */
134 if (buf
[0] == 0xf9) /* Graphic Control Extension */
136 gif_get_block(fp
, buf
);
137 if (buf
[0] & 1) /* Get transparent color index */
138 transparent
= buf
[3];
141 while (gif_get_block(fp
, buf
) != 0);
144 case ',' : /* cupsImage data */
145 fread(buf
, 9, 1, fp
);
147 if (buf
[8] & GIF_COLORMAP
)
149 ncolors
= 2 << (buf
[8] & 0x07);
150 gray
= primary
== CUPS_IMAGE_BLACK
|| primary
== CUPS_IMAGE_WHITE
;
152 if (gif_read_cmap(fp
, ncolors
, cmap
, &gray
))
159 if (transparent
>= 0)
162 * Make transparent color white...
165 cmap
[transparent
][0] = 255;
166 cmap
[transparent
][1] = 255;
167 cmap
[transparent
][2] = 255;
174 case CUPS_IMAGE_CMYK
:
175 for (i
= ncolors
- 1; i
>= 0; i
--)
176 cupsImageWhiteToCMYK(cmap
[i
], cmap
[i
], 1);
178 case CUPS_IMAGE_CMY
:
179 for (i
= ncolors
- 1; i
>= 0; i
--)
180 cupsImageWhiteToCMY(cmap
[i
], cmap
[i
], 1);
182 case CUPS_IMAGE_BLACK
:
183 for (i
= ncolors
- 1; i
>= 0; i
--)
184 cupsImageWhiteToBlack(cmap
[i
], cmap
[i
], 1);
186 case CUPS_IMAGE_WHITE
:
188 case CUPS_IMAGE_RGB
:
189 case CUPS_IMAGE_RGB_CMYK
:
190 for (i
= ncolors
- 1; i
>= 0; i
--)
191 cupsImageWhiteToRGB(cmap
[i
], cmap
[i
], 1);
195 img
->colorspace
= secondary
;
199 if (hue
!= 0 || saturation
!= 100)
200 for (i
= ncolors
- 1; i
>= 0; i
--)
201 cupsImageRGBAdjust(cmap
[i
], 1, saturation
, hue
);
205 case CUPS_IMAGE_CMYK
:
206 for (i
= ncolors
- 1; i
>= 0; i
--)
207 cupsImageRGBToCMYK(cmap
[i
], cmap
[i
], 1);
209 case CUPS_IMAGE_CMY
:
210 for (i
= ncolors
- 1; i
>= 0; i
--)
211 cupsImageRGBToCMY(cmap
[i
], cmap
[i
], 1);
213 case CUPS_IMAGE_BLACK
:
214 for (i
= ncolors
- 1; i
>= 0; i
--)
215 cupsImageRGBToBlack(cmap
[i
], cmap
[i
], 1);
217 case CUPS_IMAGE_WHITE
:
218 for (i
= ncolors
- 1; i
>= 0; i
--)
219 cupsImageRGBToWhite(cmap
[i
], cmap
[i
], 1);
221 case CUPS_IMAGE_RGB
:
222 case CUPS_IMAGE_RGB_CMYK
:
223 for (i
= ncolors
- 1; i
>= 0; i
--)
224 cupsImageRGBToRGB(cmap
[i
], cmap
[i
], 1);
228 img
->colorspace
= primary
;
233 bpp
= cupsImageGetDepth(img
);
235 for (i
= ncolors
- 1; i
>= 0; i
--)
236 cupsImageLut(cmap
[i
], bpp
, lut
);
239 img
->xsize
= (buf
[5] << 8) | buf
[4];
240 img
->ysize
= (buf
[7] << 8) | buf
[6];
243 * Check the dimensions of the image; since the dimensions are
244 * a 16-bit integer we just need to check for 0...
247 if (img
->xsize
== 0 || img
->ysize
== 0)
249 fprintf(stderr
, "ERROR: Bad GIF image dimensions: %dx%d\n",
250 img
->xsize
, img
->ysize
);
255 i
= gif_read_image(fp
, img
, cmap
, buf
[8] & GIF_INTERLACE
);
264 * 'gif_get_block()' - Read a GIF data block...
267 static int /* O - Number characters read */
268 gif_get_block(FILE *fp
, /* I - File to read from */
269 unsigned char *buf
) /* I - Input buffer */
271 int count
; /* Number of character to read */
275 * Read the count byte followed by the data from the file...
278 if ((count
= getc(fp
)) == EOF
)
285 else if (fread(buf
, 1, count
, fp
) < count
)
298 * 'gif_get_code()' - Get a LZW code from the file...
301 static int /* O - LZW code */
302 gif_get_code(FILE *fp
, /* I - File to read from */
303 int code_size
, /* I - Size of code in bits */
304 int first_time
) /* I - 1 = first time, 0 = not first time */
306 unsigned i
, j
, /* Looping vars */
307 ret
; /* Return value */
308 int count
; /* Number of bytes read */
309 static unsigned char buf
[280]; /* Input buffer */
310 static unsigned curbit
, /* Current bit */
311 lastbit
, /* Last bit in buffer */
312 done
, /* Done with this buffer? */
313 last_byte
; /* Last byte in buffer */
314 static const unsigned char bits
[8] = /* Bit masks for codes */
316 0x01, 0x02, 0x04, 0x08,
317 0x10, 0x20, 0x40, 0x80
324 * Just initialize the input buffer...
335 if ((curbit
+ code_size
) >= lastbit
)
338 * Don't have enough bits to hold the code...
342 return (-1); /* Sorry, no more... */
345 * Move last two bytes to front of buffer...
350 buf
[0] = buf
[last_byte
- 2];
351 buf
[1] = buf
[last_byte
- 1];
354 else if (last_byte
== 1)
356 buf
[0] = buf
[last_byte
- 1];
361 * Read in another buffer...
364 if ((count
= gif_get_block (fp
, buf
+ last_byte
)) <= 0)
367 * Whoops, no more data!
375 * Update buffer state...
378 curbit
= (curbit
- lastbit
) + 8 * last_byte
;
380 lastbit
= last_byte
* 8;
384 for (ret
= 0, i
= curbit
+ code_size
- 1, j
= code_size
;
387 ret
= (ret
<< 1) | ((buf
[i
/ 8] & bits
[i
& 7]) != 0);
396 * 'gif_read_cmap()' - Read the colormap from a GIF file...
399 static int /* O - -1 on error, 0 on success */
400 gif_read_cmap(FILE *fp
, /* I - File to read from */
401 int ncolors
, /* I - Number of colors in file */
402 gif_cmap_t cmap
, /* O - Colormap information */
403 int *gray
) /* IO - Is the image grayscale? */
405 int i
; /* Looping var */
409 * Read the colormap...
412 for (i
= 0; i
< ncolors
; i
++)
413 if (fread(cmap
[i
], 3, 1, fp
) < 1)
417 * Check to see if the colormap is a grayscale ramp...
420 for (i
= 0; i
< ncolors
; i
++)
421 if (cmap
[i
][0] != cmap
[i
][1] || cmap
[i
][1] != cmap
[i
][2])
431 * If this needs to be a grayscale image, convert the RGB values to
432 * luminance values...
436 for (i
= 0; i
< ncolors
; i
++)
437 cmap
[i
][0] = (cmap
[i
][0] * 31 + cmap
[i
][1] * 61 + cmap
[i
][2] * 8) / 100;
444 * 'gif_read_image()' - Read a GIF image stream...
447 static int /* I - 0 = success, -1 = failure */
448 gif_read_image(FILE *fp
, /* I - Input file */
449 cups_image_t
*img
, /* I - cupsImage pointer */
450 gif_cmap_t cmap
, /* I - Colormap */
451 int interlace
) /* I - Non-zero = interlaced image */
453 unsigned char code_size
; /* Code size */
454 cups_ib_t
*pixels
, /* Pixel buffer */
455 *temp
; /* Current pixel */
456 int xpos
, /* Current X position */
457 ypos
, /* Current Y position */
458 pass
; /* Current pass */
459 int pixel
; /* Current pixel */
460 int bpp
; /* Bytes per pixel */
461 static const int xpasses
[4] = /* X interleaving */
463 ypasses
[5] = /* Y interleaving */
464 { 0, 4, 2, 1, 999999 };
467 bpp
= cupsImageGetDepth(img
);
468 pixels
= calloc(bpp
, img
->xsize
);
472 code_size
= getc(fp
);
474 if (gif_read_lzw(fp
, 1, code_size
) < 0)
478 while ((pixel
= gif_read_lzw(fp
, 0, code_size
)) >= 0)
483 temp
[3] = cmap
[pixel
][3];
485 temp
[2] = cmap
[pixel
][2];
487 temp
[1] = cmap
[pixel
][1];
489 temp
[0] = cmap
[pixel
][0];
494 if (xpos
== img
->xsize
)
496 _cupsImagePutRow(img
, 0, ypos
, img
->xsize
, pixels
);
503 ypos
+= xpasses
[pass
];
505 if (ypos
>= img
->ysize
)
509 ypos
= ypasses
[pass
];
516 if (ypos
>= img
->ysize
)
527 * 'gif_read_lzw()' - Read a byte from the LZW stream...
530 static int /* I - Byte from stream */
531 gif_read_lzw(FILE *fp
, /* I - File to read from */
532 int first_time
, /* I - 1 = first time, 0 = not first time */
533 int input_code_size
) /* I - Code size in bits */
535 int i
, /* Looping var */
536 code
, /* Current code */
537 incode
; /* Input code */
538 static short fresh
= 0, /* 1 = empty buffers */
539 code_size
, /* Current code size */
540 set_code_size
, /* Initial code size set */
541 max_code
, /* Maximum code used */
542 max_code_size
, /* Maximum code size */
543 firstcode
, /* First code read */
544 oldcode
, /* Last code read */
545 clear_code
, /* Clear code for LZW input */
546 end_code
, /* End code for LZW input */
547 *stack
= NULL
, /* Output stack */
548 *sp
; /* Current stack pointer */
549 static gif_table_t
*table
= NULL
; /* String table */
558 set_code_size
= input_code_size
;
559 code_size
= set_code_size
+ 1;
560 clear_code
= 1 << set_code_size
;
561 end_code
= clear_code
+ 1;
562 max_code_size
= 2 * clear_code
;
563 max_code
= clear_code
+ 2;
566 * Allocate memory for buffers...
570 table
= calloc(2, sizeof(gif_table_t
));
576 stack
= calloc(8192, sizeof(short));
582 * Initialize input buffers...
585 gif_get_code(fp
, 0, 1);
588 * Wipe the decompressor table...
593 for (i
= 0; i
< clear_code
; i
++)
599 for (; i
< 4096; i
++)
600 table
[0][i
] = table
[1][0] = 0;
611 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
612 while (firstcode
== clear_code
);
620 while ((code
= gif_get_code (fp
, code_size
, 0)) >= 0)
622 if (code
== clear_code
)
624 for (i
= 0; i
< clear_code
; i
++)
630 for (; i
< 4096; i
++)
631 table
[0][i
] = table
[1][i
] = 0;
633 code_size
= set_code_size
+ 1;
634 max_code_size
= 2 * clear_code
;
635 max_code
= clear_code
+ 2;
639 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
643 else if (code
== end_code
)
645 unsigned char buf
[260];
649 while (gif_get_block(fp
, buf
) > 0);
656 if (code
>= max_code
)
662 while (code
>= clear_code
)
664 *sp
++ = table
[1][code
];
665 if (code
== table
[0][code
])
668 code
= table
[0][code
];
671 *sp
++ = firstcode
= table
[1][code
];
676 table
[0][code
] = oldcode
;
677 table
[1][code
] = firstcode
;
680 if (max_code
>= max_code_size
&& max_code_size
< 4096)
698 * End of "$Id: image-gif.c 177 2006-06-21 00:20:03Z jlovell $".