]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-gif.c
2 * "$Id: image-gif.c 4741 2005-10-02 04:25:52Z mike $"
4 * GIF image routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2005 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
:
226 img
->colorspace
= primary
;
231 bpp
= cupsImageGetDepth(img
);
233 for (i
= ncolors
- 1; i
>= 0; i
--)
234 cupsImageLut(cmap
[i
], bpp
, lut
);
237 img
->xsize
= (buf
[5] << 8) | buf
[4];
238 img
->ysize
= (buf
[7] << 8) | buf
[6];
241 * Check the dimensions of the image; since the dimensions are
242 * a 16-bit integer we just need to check for 0...
245 if (img
->xsize
== 0 || img
->ysize
== 0)
247 fprintf(stderr
, "ERROR: Bad GIF image dimensions: %dx%d\n",
248 img
->xsize
, img
->ysize
);
253 i
= gif_read_image(fp
, img
, cmap
, buf
[8] & GIF_INTERLACE
);
262 * 'gif_get_block()' - Read a GIF data block...
265 static int /* O - Number characters read */
266 gif_get_block(FILE *fp
, /* I - File to read from */
267 unsigned char *buf
) /* I - Input buffer */
269 int count
; /* Number of character to read */
273 * Read the count byte followed by the data from the file...
276 if ((count
= getc(fp
)) == EOF
)
283 else if (fread(buf
, 1, count
, fp
) < count
)
296 * 'gif_get_code()' - Get a LZW code from the file...
299 static int /* O - LZW code */
300 gif_get_code(FILE *fp
, /* I - File to read from */
301 int code_size
, /* I - Size of code in bits */
302 int first_time
) /* I - 1 = first time, 0 = not first time */
304 unsigned i
, j
, /* Looping vars */
305 ret
; /* Return value */
306 int count
; /* Number of bytes read */
307 static unsigned char buf
[280]; /* Input buffer */
308 static unsigned curbit
, /* Current bit */
309 lastbit
, /* Last bit in buffer */
310 done
, /* Done with this buffer? */
311 last_byte
; /* Last byte in buffer */
312 static const unsigned char bits
[8] = /* Bit masks for codes */
314 0x01, 0x02, 0x04, 0x08,
315 0x10, 0x20, 0x40, 0x80
322 * Just initialize the input buffer...
333 if ((curbit
+ code_size
) >= lastbit
)
336 * Don't have enough bits to hold the code...
340 return (-1); /* Sorry, no more... */
343 * Move last two bytes to front of buffer...
348 buf
[0] = buf
[last_byte
- 2];
349 buf
[1] = buf
[last_byte
- 1];
352 else if (last_byte
== 1)
354 buf
[0] = buf
[last_byte
- 1];
359 * Read in another buffer...
362 if ((count
= gif_get_block (fp
, buf
+ last_byte
)) <= 0)
365 * Whoops, no more data!
373 * Update buffer state...
376 curbit
= (curbit
- lastbit
) + 8 * last_byte
;
378 lastbit
= last_byte
* 8;
382 for (ret
= 0, i
= curbit
+ code_size
- 1, j
= code_size
;
385 ret
= (ret
<< 1) | ((buf
[i
/ 8] & bits
[i
& 7]) != 0);
394 * 'gif_read_cmap()' - Read the colormap from a GIF file...
397 static int /* O - -1 on error, 0 on success */
398 gif_read_cmap(FILE *fp
, /* I - File to read from */
399 int ncolors
, /* I - Number of colors in file */
400 gif_cmap_t cmap
, /* O - Colormap information */
401 int *gray
) /* IO - Is the image grayscale? */
403 int i
; /* Looping var */
407 * Read the colormap...
410 for (i
= 0; i
< ncolors
; i
++)
411 if (fread(cmap
[i
], 3, 1, fp
) < 1)
415 * Check to see if the colormap is a grayscale ramp...
418 for (i
= 0; i
< ncolors
; i
++)
419 if (cmap
[i
][0] != cmap
[i
][1] || cmap
[i
][1] != cmap
[i
][2])
429 * If this needs to be a grayscale image, convert the RGB values to
430 * luminance values...
434 for (i
= 0; i
< ncolors
; i
++)
435 cmap
[i
][0] = (cmap
[i
][0] * 31 + cmap
[i
][1] * 61 + cmap
[i
][2] * 8) / 100;
442 * 'gif_read_image()' - Read a GIF image stream...
445 static int /* I - 0 = success, -1 = failure */
446 gif_read_image(FILE *fp
, /* I - Input file */
447 cups_image_t
*img
, /* I - cupsImage pointer */
448 gif_cmap_t cmap
, /* I - Colormap */
449 int interlace
) /* I - Non-zero = interlaced image */
451 unsigned char code_size
; /* Code size */
452 cups_ib_t
*pixels
, /* Pixel buffer */
453 *temp
; /* Current pixel */
454 int xpos
, /* Current X position */
455 ypos
, /* Current Y position */
456 pass
; /* Current pass */
457 int pixel
; /* Current pixel */
458 int bpp
; /* Bytes per pixel */
459 static const int xpasses
[4] = /* X interleaving */
461 ypasses
[5] = /* Y interleaving */
462 { 0, 4, 2, 1, 999999 };
465 bpp
= cupsImageGetDepth(img
);
466 pixels
= calloc(bpp
, img
->xsize
);
470 code_size
= getc(fp
);
472 if (gif_read_lzw(fp
, 1, code_size
) < 0)
476 while ((pixel
= gif_read_lzw(fp
, 0, code_size
)) >= 0)
481 temp
[3] = cmap
[pixel
][3];
483 temp
[2] = cmap
[pixel
][2];
485 temp
[1] = cmap
[pixel
][1];
487 temp
[0] = cmap
[pixel
][0];
492 if (xpos
== img
->xsize
)
494 _cupsImagePutRow(img
, 0, ypos
, img
->xsize
, pixels
);
501 ypos
+= xpasses
[pass
];
503 if (ypos
>= img
->ysize
)
507 ypos
= ypasses
[pass
];
514 if (ypos
>= img
->ysize
)
525 * 'gif_read_lzw()' - Read a byte from the LZW stream...
528 static int /* I - Byte from stream */
529 gif_read_lzw(FILE *fp
, /* I - File to read from */
530 int first_time
, /* I - 1 = first time, 0 = not first time */
531 int input_code_size
) /* I - Code size in bits */
533 int i
, /* Looping var */
534 code
, /* Current code */
535 incode
; /* Input code */
536 static short fresh
= 0, /* 1 = empty buffers */
537 code_size
, /* Current code size */
538 set_code_size
, /* Initial code size set */
539 max_code
, /* Maximum code used */
540 max_code_size
, /* Maximum code size */
541 firstcode
, /* First code read */
542 oldcode
, /* Last code read */
543 clear_code
, /* Clear code for LZW input */
544 end_code
, /* End code for LZW input */
545 *stack
= NULL
, /* Output stack */
546 *sp
; /* Current stack pointer */
547 static gif_table_t
*table
= NULL
; /* String table */
556 set_code_size
= input_code_size
;
557 code_size
= set_code_size
+ 1;
558 clear_code
= 1 << set_code_size
;
559 end_code
= clear_code
+ 1;
560 max_code_size
= 2 * clear_code
;
561 max_code
= clear_code
+ 2;
564 * Allocate memory for buffers...
568 table
= calloc(2, sizeof(gif_table_t
));
574 stack
= calloc(8192, sizeof(short));
580 * Initialize input buffers...
583 gif_get_code(fp
, 0, 1);
586 * Wipe the decompressor table...
591 for (i
= 0; i
< clear_code
; i
++)
597 for (; i
< 4096; i
++)
598 table
[0][i
] = table
[1][0] = 0;
609 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
610 while (firstcode
== clear_code
);
618 while ((code
= gif_get_code (fp
, code_size
, 0)) >= 0)
620 if (code
== clear_code
)
622 for (i
= 0; i
< clear_code
; i
++)
628 for (; i
< 4096; i
++)
629 table
[0][i
] = table
[1][i
] = 0;
631 code_size
= set_code_size
+ 1;
632 max_code_size
= 2 * clear_code
;
633 max_code
= clear_code
+ 2;
637 firstcode
= oldcode
= gif_get_code(fp
, code_size
, 0);
641 else if (code
== end_code
)
643 unsigned char buf
[260];
647 while (gif_get_block(fp
, buf
) > 0);
654 if (code
>= max_code
)
660 while (code
>= clear_code
)
662 *sp
++ = table
[1][code
];
663 if (code
== table
[0][code
])
666 code
= table
[0][code
];
669 *sp
++ = firstcode
= table
[1][code
];
674 table
[0][code
] = oldcode
;
675 table
[1][code
] = firstcode
;
678 if (max_code
>= max_code_size
&& max_code_size
< 4096)
696 * End of "$Id: image-gif.c 4741 2005-10-02 04:25:52Z mike $".