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