1 /*
2 * GIF image routines for CUPS.
3 *
4 * Copyright 2007-2011 by Apple Inc.
5 * Copyright 1993-2007 by Easy Software Products.
6 *
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "COPYING"
10 * which should have been included with this file.
11 *
12 * Contents:
13 *
14 * _cupsImageReadGIF() - Read a GIF image file.
15 * gif_get_block() - Read a GIF data block...
16 * gif_get_code() - Get a LZW code from the file...
17 * gif_read_cmap() - Read the colormap from a GIF file...
18 * gif_read_image() - Read a GIF image stream...
19 * gif_read_lzw() - Read a byte from the LZW stream...
20 */
21
22 /*
23 * Include necessary headers...
24 */
25
26 #include "image-private.h"
27
28
29 /*
30 * GIF definitions...
31 */
32
33 #define GIF_INTERLACE 0x40
34 #define GIF_COLORMAP 0x80
35 #define GIF_MAX_BITS 12
36
37 typedef cups_ib_t gif_cmap_t[256][4];
38 typedef short gif_table_t[4096];
39
40
41 /*
42 * Local globals...
43 */
44
45 static int gif_eof = 0; /* Did we hit EOF? */
46
47
48 /*
49 * Local functions...
50 */
51
52 static int gif_get_block(FILE *fp, unsigned char *buffer);
53 static int gif_get_code (FILE *fp, int code_size, int first_time);
54 static int gif_read_cmap(FILE *fp, int ncolors, gif_cmap_t cmap,
55 int *gray);
56 static int gif_read_image(FILE *fp, cups_image_t *img, gif_cmap_t cmap,
57 int interlace);
58 static int gif_read_lzw(FILE *fp, int first_time, int input_code_size);
59
60
61 /*
62 * '_cupsImageReadGIF()' - Read a GIF image file.
63 */
64
65 int /* O - Read status */
_cupsImageReadGIF(cups_image_t * img,FILE * fp,cups_icspace_t primary,cups_icspace_t secondary,int saturation,int hue,const cups_ib_t * lut)66 _cupsImageReadGIF(
67 cups_image_t *img, /* IO - cupsImage */
68 FILE *fp, /* I - cupsImage file */
69 cups_icspace_t primary, /* I - Primary choice for colorspace */
70 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
71 int saturation, /* I - Color saturation (%) */
72 int hue, /* I - Color hue (degrees) */
73 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
74 {
75 unsigned char buf[1024]; /* Input buffer */
76 gif_cmap_t cmap; /* Colormap */
77 int i, /* Looping var */
78 bpp, /* Bytes per pixel */
79 gray, /* Grayscale image? */
80 ncolors, /* Bits per pixel */
81 transparent; /* Transparent color index */
82
83
84 /*
85 * GIF files are either grayscale or RGB - no CMYK...
86 */
87
88 if (primary == CUPS_IMAGE_RGB_CMYK)
89 primary = CUPS_IMAGE_RGB;
90
91 /*
92 * Read the header; we already know it is a GIF file...
93 */
94
95 if (fread(buf, 13, 1, fp) == 0 && ferror(fp))
96 DEBUG_printf(("Error reading file!"));
97
98 img->xsize = (buf[7] << 8) | buf[6];
99 img->ysize = (buf[9] << 8) | buf[8];
100 ncolors = 2 << (buf[10] & 0x07);
101 gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
102
103 if (buf[10] & GIF_COLORMAP)
104 if (gif_read_cmap(fp, ncolors, cmap, &gray))
105 {
106 fclose(fp);
107 return (-1);
108 }
109
110 transparent = -1;
111
112 for (;;)
113 {
114 switch (getc(fp))
115 {
116 case ';' : /* End of image */
117 fclose(fp);
118 return (-1); /* Early end of file */
119
120 case '!' : /* Extension record */
121 buf[0] = getc(fp);
122 if (buf[0] == 0xf9) /* Graphic Control Extension */
123 {
124 gif_get_block(fp, buf);
125 if (buf[0] & 1) /* Get transparent color index */
126 transparent = buf[3];
127 }
128
129 while (gif_get_block(fp, buf) != 0)
130 {
131 if(gif_eof)
132 {
133 return (-1);
134 }
135 }
136 break;
137
138 case ',' : /* cupsImage data */
139 if (fread(buf, 9, 1, fp) == 0 && ferror(fp))
140 DEBUG_printf(("Error reading file!"));
141
142 if (buf[8] & GIF_COLORMAP)
143 {
144 ncolors = 2 << (buf[8] & 0x07);
145 gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;
146
147 if (gif_read_cmap(fp, ncolors, cmap, &gray))
148 {
149 fclose(fp);
150 return (-1);
151 }
152 }
153
154 if (transparent >= 0)
155 {
156 /*
157 * Make transparent color white...
158 */
159
160 cmap[transparent][0] = 255;
161 cmap[transparent][1] = 255;
162 cmap[transparent][2] = 255;
163 }
164
165 if (gray)
166 {
167 switch (secondary)
168 {
169 case CUPS_IMAGE_CMYK :
170 for (i = ncolors - 1; i >= 0; i --)
171 cupsImageWhiteToCMYK(cmap[i], cmap[i], 1);
172 break;
173 case CUPS_IMAGE_CMY :
174 for (i = ncolors - 1; i >= 0; i --)
175 cupsImageWhiteToCMY(cmap[i], cmap[i], 1);
176 break;
177 case CUPS_IMAGE_BLACK :
178 for (i = ncolors - 1; i >= 0; i --)
179 cupsImageWhiteToBlack(cmap[i], cmap[i], 1);
180 break;
181 case CUPS_IMAGE_WHITE :
182 break;
183 case CUPS_IMAGE_RGB :
184 case CUPS_IMAGE_RGB_CMYK :
185 for (i = ncolors - 1; i >= 0; i --)
186 cupsImageWhiteToRGB(cmap[i], cmap[i], 1);
187 break;
188 }
189
190 img->colorspace = secondary;
191 }
192 else
193 {
194 if (hue != 0 || saturation != 100)
195 for (i = ncolors - 1; i >= 0; i --)
196 cupsImageRGBAdjust(cmap[i], 1, saturation, hue);
197
198 switch (primary)
199 {
200 case CUPS_IMAGE_CMYK :
201 for (i = ncolors - 1; i >= 0; i --)
202 cupsImageRGBToCMYK(cmap[i], cmap[i], 1);
203 break;
204 case CUPS_IMAGE_CMY :
205 for (i = ncolors - 1; i >= 0; i --)
206 cupsImageRGBToCMY(cmap[i], cmap[i], 1);
207 break;
208 case CUPS_IMAGE_BLACK :
209 for (i = ncolors - 1; i >= 0; i --)
210 cupsImageRGBToBlack(cmap[i], cmap[i], 1);
211 break;
212 case CUPS_IMAGE_WHITE :
213 for (i = ncolors - 1; i >= 0; i --)
214 cupsImageRGBToWhite(cmap[i], cmap[i], 1);
215 break;
216 case CUPS_IMAGE_RGB :
217 case CUPS_IMAGE_RGB_CMYK :
218 for (i = ncolors - 1; i >= 0; i --)
219 cupsImageRGBToRGB(cmap[i], cmap[i], 1);
220 break;
221 }
222
223 img->colorspace = primary;
224 }
225
226 if (lut)
227 {
228 bpp = cupsImageGetDepth(img);
229
230 for (i = ncolors - 1; i >= 0; i --)
231 cupsImageLut(cmap[i], bpp, lut);
232 }
233
234 img->xsize = (buf[5] << 8) | buf[4];
235 img->ysize = (buf[7] << 8) | buf[6];
236
237 /*
238 * Check the dimensions of the image; since the dimensions are
239 * a 16-bit integer we just need to check for 0...
240 */
241
242 if (img->xsize == 0 || img->ysize == 0)
243 {
244 fprintf(stderr, "DEBUG: Bad GIF image dimensions: %dx%d\n",
245 img->xsize, img->ysize);
246 fclose(fp);
247 return (1);
248 }
249
250 i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE);
251 fclose(fp);
252 return (i);
253 }
254 }
255 }
256
257
258 /*
259 * 'gif_get_block()' - Read a GIF data block...
260 */
261
262 static int /* O - Number characters read */
gif_get_block(FILE * fp,unsigned char * buf)263 gif_get_block(FILE *fp, /* I - File to read from */
264 unsigned char *buf) /* I - Input buffer */
265 {
266 int count; /* Number of character to read */
267
268
269 /*
270 * Read the count byte followed by the data from the file...
271 */
272
273 if ((count = getc(fp)) == EOF)
274 {
275 gif_eof = 1;
276 return (-1);
277 }
278 else if (count == 0)
279 gif_eof = 1;
280 else if (fread(buf, 1, count, fp) < count)
281 {
282 gif_eof = 1;
283 return (-1);
284 }
285 else
286 gif_eof = 0;
287
288 return (count);
289 }
290
291
292 /*
293 * 'gif_get_code()' - Get a LZW code from the file...
294 */
295
296 static int /* O - LZW code */
gif_get_code(FILE * fp,int code_size,int first_time)297 gif_get_code(FILE *fp, /* I - File to read from */
298 int code_size, /* I - Size of code in bits */
299 int first_time) /* I - 1 = first time, 0 = not first time */
300 {
301 unsigned i, j, /* Looping vars */
302 ret; /* Return value */
303 int count; /* Number of bytes read */
304 static unsigned char buf[280]; /* Input buffer */
305 static unsigned curbit, /* Current bit */
306 lastbit, /* Last bit in buffer */
307 done, /* Done with this buffer? */
308 last_byte; /* Last byte in buffer */
309 static const unsigned char bits[8] = /* Bit masks for codes */
310 {
311 0x01, 0x02, 0x04, 0x08,
312 0x10, 0x20, 0x40, 0x80
313 };
314
315
316 if (first_time)
317 {
318 /*
319 * Just initialize the input buffer...
320 */
321
322 curbit = 0;
323 lastbit = 0;
324 last_byte = 0;
325 done = 0;
326
327 return (0);
328 }
329
330 if ((curbit + code_size) >= lastbit)
331 {
332 /*
333 * Don't have enough bits to hold the code...
334 */
335
336 if (done)
337 return (-1); /* Sorry, no more... */
338
339 /*
340 * Move last two bytes to front of buffer...
341 */
342
343 if (last_byte > 1)
344 {
345 buf[0] = buf[last_byte - 2];
346 buf[1] = buf[last_byte - 1];
347 last_byte = 2;
348 }
349 else if (last_byte == 1)
350 {
351 buf[0] = buf[last_byte - 1];
352 last_byte = 1;
353 }
354
355 /*
356 * Read in another buffer...
357 */
358
359 if ((count = gif_get_block(fp, buf + last_byte)) <= 0)
360 {
361 /*
362 * Whoops, no more data!
363 */
364
365 done = 1;
366 return (-1);
367 }
368
369 /*
370 * Update buffer state...
371 */
372
373 curbit = (curbit - lastbit) + 8 * last_byte;
374 last_byte += count;
375 lastbit = last_byte * 8;
376 }
377
378 for (ret = 0, i = curbit + code_size - 1, j = code_size;
379 j > 0;
380 i --, j --)
381 ret = (ret << 1) | ((buf[i / 8] & bits[i & 7]) != 0);
382
383 curbit += code_size;
384
385 return ret;
386 }
387
388
389 /*
390 * 'gif_read_cmap()' - Read the colormap from a GIF file...
391 */
392
393 static int /* O - -1 on error, 0 on success */
gif_read_cmap(FILE * fp,int ncolors,gif_cmap_t cmap,int * gray)394 gif_read_cmap(FILE *fp, /* I - File to read from */
395 int ncolors, /* I - Number of colors in file */
396 gif_cmap_t cmap, /* O - Colormap information */
397 int *gray) /* IO - Is the image grayscale? */
398 {
399 int i; /* Looping var */
400
401
402 /*
403 * Read the colormap...
404 */
405
406 for (i = 0; i < ncolors; i ++)
407 if (fread(cmap[i], 3, 1, fp) < 1)
408 return (-1);
409
410 /*
411 * Check to see if the colormap is a grayscale ramp...
412 */
413
414 for (i = 0; i < ncolors; i ++)
415 if (cmap[i][0] != cmap[i][1] || cmap[i][1] != cmap[i][2])
416 break;
417
418 if (i == ncolors)
419 {
420 *gray = 1;
421 return (0);
422 }
423
424 /*
425 * If this needs to be a grayscale image, convert the RGB values to
426 * luminance values...
427 */
428
429 if (*gray)
430 for (i = 0; i < ncolors; i ++)
431 cmap[i][0] = (cmap[i][0] * 31 + cmap[i][1] * 61 + cmap[i][2] * 8) / 100;
432
433 return (0);
434 }
435
436
437 /*
438 * 'gif_read_image()' - Read a GIF image stream...
439 */
440
441 static int /* I - 0 = success, -1 = failure */
gif_read_image(FILE * fp,cups_image_t * img,gif_cmap_t cmap,int interlace)442 gif_read_image(FILE *fp, /* I - Input file */
443 cups_image_t *img, /* I - cupsImage pointer */
444 gif_cmap_t cmap, /* I - Colormap */
445 int interlace) /* I - Non-zero = interlaced image */
446 {
447 unsigned char code_size; /* Code size */
448 cups_ib_t *pixels, /* Pixel buffer */
449 *temp; /* Current pixel */
450 int xpos, /* Current X position */
451 ypos, /* Current Y position */
452 pass; /* Current pass */
453 int pixel; /* Current pixel */
454 int bpp; /* Bytes per pixel */
455 static const int xpasses[4] = /* X interleaving */
456 { 8, 8, 4, 2 },
457 ypasses[5] = /* Y interleaving */
458 { 0, 4, 2, 1, 999999 };
459
460
461 bpp = cupsImageGetDepth(img);
462 pixels = calloc(bpp, img->xsize);
463 xpos = 0;
464 ypos = 0;
465 pass = 0;
466 code_size = getc(fp);
467
468 if (!pixels)
469 return (-1);
470
471 if (code_size > GIF_MAX_BITS || gif_read_lzw(fp, 1, code_size) < 0)
472 {
473 free(pixels);
474 return (-1);
475 }
476
477 temp = pixels;
478 while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0)
479 {
480 switch (bpp)
481 {
482 case 4 :
483 temp[3] = cmap[pixel][3];
484 case 3 :
485 temp[2] = cmap[pixel][2];
486 case 2 :
487 temp[1] = cmap[pixel][1];
488 default :
489 temp[0] = cmap[pixel][0];
490 }
491
492 xpos ++;
493 temp += bpp;
494 if (xpos == img->xsize)
495 {
496 int res = _cupsImagePutRow(img, 0, ypos, img->xsize, pixels);
497 if(res)
498 {
499 return (-1);
500 }
501 xpos = 0;
502 temp = pixels;
503
504 if (interlace)
505 {
506 ypos += xpasses[pass];
507
508 if (ypos >= img->ysize)
509 {
510 pass ++;
511
512 ypos = ypasses[pass];
513 }
514 }
515 else
516 ypos ++;
517 }
518
519 if (ypos >= img->ysize)
520 break;
521 }
522
523 free(pixels);
524
525 return (0);
526 }
527
528
529 /*
530 * 'gif_read_lzw()' - Read a byte from the LZW stream...
531 */
532
533 static int /* I - Byte from stream */
gif_read_lzw(FILE * fp,int first_time,int input_code_size)534 gif_read_lzw(FILE *fp, /* I - File to read from */
535 int first_time, /* I - 1 = first time, 0 = not first time */
536 int input_code_size) /* I - Code size in bits */
537 {
538 int i, /* Looping var */
539 code, /* Current code */
540 incode; /* Input code */
541 static short fresh = 0, /* 1 = empty buffers */
542 code_size, /* Current code size */
543 set_code_size, /* Initial code size set */
544 max_code, /* Maximum code used */
545 max_code_size, /* Maximum code size */
546 firstcode, /* First code read */
547 oldcode, /* Last code read */
548 clear_code, /* Clear code for LZW input */
549 end_code, /* End code for LZW input */
550 *stack = NULL, /* Output stack */
551 *sp; /* Current stack pointer */
552 static gif_table_t *table = NULL; /* String table */
553
554
555 if (first_time)
556 {
557 /*
558 * Setup LZW state...
559 */
560
561 set_code_size = input_code_size;
562 code_size = set_code_size + 1;
563 clear_code = 1 << set_code_size;
564 end_code = clear_code + 1;
565 max_code_size = 2 * clear_code;
566 max_code = clear_code + 2;
567
568 /*
569 * Allocate memory for buffers...
570 */
571
572 if (table == NULL)
573 table = calloc(2, sizeof(gif_table_t));
574
575 if (table == NULL)
576 return (-1);
577
578 if (stack == NULL)
579 stack = calloc(8192, sizeof(short));
580
581 if (stack == NULL)
582 return (-1);
583
584 /*
585 * Initialize input buffers...
586 */
587
588 gif_get_code(fp, 0, 1);
589
590 /*
591 * Wipe the decompressor table (already mostly 0 due to the calloc above...)
592 */
593
594 fresh = 1;
595
596 for (i = 1; i < clear_code; i ++)
597 table[1][i] = i;
598
599 sp = stack;
600
601 return (0);
602 }
603 else if (fresh)
604 {
605 fresh = 0;
606
607 do
608 {
609 firstcode = oldcode = gif_get_code(fp, code_size, 0);
610 }
611 while (firstcode == clear_code);
612
613 return (firstcode & 255);
614 }
615 else if (!table)
616 return (0);
617
618 if (sp > stack)
619 return ((*--sp) & 255);
620
621 while ((code = gif_get_code(fp, code_size, 0)) >= 0)
622 {
623 if (code == clear_code)
624 {
625 /*
626 * Clear/reset the compression table...
627 */
628
629 memset(table, 0, 2 * sizeof(gif_table_t));
630 for (i = 1; i < clear_code; i ++)
631 table[1][i] = i;
632
633 code_size = set_code_size + 1;
634 max_code_size = 2 * clear_code;
635 max_code = clear_code + 2;
636
637 sp = stack;
638
639 firstcode = oldcode = gif_get_code(fp, code_size, 0);
640
641 return (firstcode & 255);
642 }
643 else if (code == end_code || code > max_code)
644 {
645 unsigned char buf[260]; /* Block buffer */
646
647 if (!gif_eof)
648 while (gif_get_block(fp, buf) > 0);
649
650 return (-2);
651 }
652
653 incode = code;
654
655 if (code == max_code)
656 {
657 if (sp < (stack + 8192))
658 *sp++ = firstcode;
659
660 code = oldcode;
661 }
662
663 while (code >= clear_code && sp < (stack + 8192))
664 {
665 *sp++ = table[1][code];
666 if (code == table[0][code])
667 return (255);
668
669 code = table[0][code];
670 }
671
672 if (sp < (stack + 8192))
673 *sp++ = firstcode = table[1][code];
674
675 code = max_code;
676
677 if (code < 4096)
678 {
679 table[0][code] = oldcode;
680 table[1][code] = firstcode;
681 max_code ++;
682
683 if (max_code >= max_code_size && max_code_size < 4096)
684 {
685 max_code_size *= 2;
686 code_size ++;
687 }
688 }
689
690 oldcode = incode;
691
692 if (sp > stack)
693 return ((*--sp) & 255);
694 }
695
696 return (code & 255);
697 }
698
699