Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * wrgif.c
      3  *
      4  * This file was part of the Independent JPEG Group's software:
      5  * Copyright (C) 1991-1997, Thomas G. Lane.
      6  * libjpeg-turbo Modifications:
      7  * Copyright (C) 2015, D. R. Commander.
      8  * For conditions of distribution and use, see the accompanying README.ijg
      9  * file.
     10  *
     11  * This file contains routines to write output images in GIF format.
     12  *
     13  **************************************************************************
     14  * NOTE: to avoid entanglements with Unisys' patent on LZW compression,   *
     15  * this code has been modified to output "uncompressed GIF" files.        *
     16  * There is no trace of the LZW algorithm in this file.                   *
     17  **************************************************************************
     18  *
     19  * These routines may need modification for non-Unix environments or
     20  * specialized applications.  As they stand, they assume output to
     21  * an ordinary stdio stream.
     22  */
     23 
     24 /*
     25  * This code is loosely based on ppmtogif from the PBMPLUS distribution
     26  * of Feb. 1991.  That file contains the following copyright notice:
     27  *    Based on GIFENCODE by David Rowley <mgardi (at) watdscu.waterloo.edu>.
     28  *    Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
     29  *    Copyright (C) 1989 by Jef Poskanzer.
     30  *    Permission to use, copy, modify, and distribute this software and its
     31  *    documentation for any purpose and without fee is hereby granted, provided
     32  *    that the above copyright notice appear in all copies and that both that
     33  *    copyright notice and this permission notice appear in supporting
     34  *    documentation.  This software is provided "as is" without express or
     35  *    implied warranty.
     36  *
     37  * We are also required to state that
     38  *    "The Graphics Interchange Format(c) is the Copyright property of
     39  *    CompuServe Incorporated. GIF(sm) is a Service Mark property of
     40  *    CompuServe Incorporated."
     41  */
     42 
     43 #include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
     44 
     45 #ifdef GIF_SUPPORTED
     46 
     47 
     48 /* Private version of data destination object */
     49 
     50 typedef struct {
     51   struct djpeg_dest_struct pub; /* public fields */
     52 
     53   j_decompress_ptr cinfo;       /* back link saves passing separate parm */
     54 
     55   /* State for packing variable-width codes into a bitstream */
     56   int n_bits;                   /* current number of bits/code */
     57   int maxcode;                  /* maximum code, given n_bits */
     58   long cur_accum;               /* holds bits not yet output */
     59   int cur_bits;                 /* # of bits in cur_accum */
     60 
     61   /* State for GIF code assignment */
     62   int ClearCode;                /* clear code (doesn't change) */
     63   int EOFCode;                  /* EOF code (ditto) */
     64   int code_counter;             /* counts output symbols */
     65 
     66   /* GIF data packet construction buffer */
     67   int bytesinpkt;               /* # of bytes in current packet */
     68   char packetbuf[256];          /* workspace for accumulating packet */
     69 
     70 } gif_dest_struct;
     71 
     72 typedef gif_dest_struct *gif_dest_ptr;
     73 
     74 /* Largest value that will fit in N bits */
     75 #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
     76 
     77 
     78 /*
     79  * Routines to package finished data bytes into GIF data blocks.
     80  * A data block consists of a count byte (1..255) and that many data bytes.
     81  */
     82 
     83 LOCAL(void)
     84 flush_packet (gif_dest_ptr dinfo)
     85 /* flush any accumulated data */
     86 {
     87   if (dinfo->bytesinpkt > 0) {  /* never write zero-length packet */
     88     dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++;
     89     if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt)
     90         != (size_t) dinfo->bytesinpkt)
     91       ERREXIT(dinfo->cinfo, JERR_FILE_WRITE);
     92     dinfo->bytesinpkt = 0;
     93   }
     94 }
     95 
     96 
     97 /* Add a character to current packet; flush to disk if necessary */
     98 #define CHAR_OUT(dinfo,c)  \
     99         { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c);  \
    100             if ((dinfo)->bytesinpkt >= 255)  \
    101               flush_packet(dinfo);  \
    102         }
    103 
    104 
    105 /* Routine to convert variable-width codes into a byte stream */
    106 
    107 LOCAL(void)
    108 output (gif_dest_ptr dinfo, int code)
    109 /* Emit a code of n_bits bits */
    110 /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
    111 {
    112   dinfo->cur_accum |= ((long) code) << dinfo->cur_bits;
    113   dinfo->cur_bits += dinfo->n_bits;
    114 
    115   while (dinfo->cur_bits >= 8) {
    116     CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
    117     dinfo->cur_accum >>= 8;
    118     dinfo->cur_bits -= 8;
    119   }
    120 }
    121 
    122 
    123 /* The pseudo-compression algorithm.
    124  *
    125  * In this module we simply output each pixel value as a separate symbol;
    126  * thus, no compression occurs.  In fact, there is expansion of one bit per
    127  * pixel, because we use a symbol width one bit wider than the pixel width.
    128  *
    129  * GIF ordinarily uses variable-width symbols, and the decoder will expect
    130  * to ratchet up the symbol width after a fixed number of symbols.
    131  * To simplify the logic and keep the expansion penalty down, we emit a
    132  * GIF Clear code to reset the decoder just before the width would ratchet up.
    133  * Thus, all the symbols in the output file will have the same bit width.
    134  * Note that emitting the Clear codes at the right times is a mere matter of
    135  * counting output symbols and is in no way dependent on the LZW patent.
    136  *
    137  * With a small basic pixel width (low color count), Clear codes will be
    138  * needed very frequently, causing the file to expand even more.  So this
    139  * simplistic approach wouldn't work too well on bilevel images, for example.
    140  * But for output of JPEG conversions the pixel width will usually be 8 bits
    141  * (129 to 256 colors), so the overhead added by Clear symbols is only about
    142  * one symbol in every 256.
    143  */
    144 
    145 LOCAL(void)
    146 compress_init (gif_dest_ptr dinfo, int i_bits)
    147 /* Initialize pseudo-compressor */
    148 {
    149   /* init all the state variables */
    150   dinfo->n_bits = i_bits;
    151   dinfo->maxcode = MAXCODE(dinfo->n_bits);
    152   dinfo->ClearCode = (1 << (i_bits - 1));
    153   dinfo->EOFCode = dinfo->ClearCode + 1;
    154   dinfo->code_counter = dinfo->ClearCode + 2;
    155   /* init output buffering vars */
    156   dinfo->bytesinpkt = 0;
    157   dinfo->cur_accum = 0;
    158   dinfo->cur_bits = 0;
    159   /* GIF specifies an initial Clear code */
    160   output(dinfo, dinfo->ClearCode);
    161 }
    162 
    163 
    164 LOCAL(void)
    165 compress_pixel (gif_dest_ptr dinfo, int c)
    166 /* Accept and "compress" one pixel value.
    167  * The given value must be less than n_bits wide.
    168  */
    169 {
    170   /* Output the given pixel value as a symbol. */
    171   output(dinfo, c);
    172   /* Issue Clear codes often enough to keep the reader from ratcheting up
    173    * its symbol size.
    174    */
    175   if (dinfo->code_counter < dinfo->maxcode) {
    176     dinfo->code_counter++;
    177   } else {
    178     output(dinfo, dinfo->ClearCode);
    179     dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */
    180   }
    181 }
    182 
    183 
    184 LOCAL(void)
    185 compress_term (gif_dest_ptr dinfo)
    186 /* Clean up at end */
    187 {
    188   /* Send an EOF code */
    189   output(dinfo, dinfo->EOFCode);
    190   /* Flush the bit-packing buffer */
    191   if (dinfo->cur_bits > 0) {
    192     CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
    193   }
    194   /* Flush the packet buffer */
    195   flush_packet(dinfo);
    196 }
    197 
    198 
    199 /* GIF header construction */
    200 
    201 
    202 LOCAL(void)
    203 put_word (gif_dest_ptr dinfo, unsigned int w)
    204 /* Emit a 16-bit word, LSB first */
    205 {
    206   putc(w & 0xFF, dinfo->pub.output_file);
    207   putc((w >> 8) & 0xFF, dinfo->pub.output_file);
    208 }
    209 
    210 
    211 LOCAL(void)
    212 put_3bytes (gif_dest_ptr dinfo, int val)
    213 /* Emit 3 copies of same byte value --- handy subr for colormap construction */
    214 {
    215   putc(val, dinfo->pub.output_file);
    216   putc(val, dinfo->pub.output_file);
    217   putc(val, dinfo->pub.output_file);
    218 }
    219 
    220 
    221 LOCAL(void)
    222 emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap)
    223 /* Output the GIF file header, including color map */
    224 /* If colormap==NULL, synthesize a grayscale colormap */
    225 {
    226   int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
    227   int cshift = dinfo->cinfo->data_precision - 8;
    228   int i;
    229 
    230   if (num_colors > 256)
    231     ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors);
    232   /* Compute bits/pixel and related values */
    233   BitsPerPixel = 1;
    234   while (num_colors > (1 << BitsPerPixel))
    235     BitsPerPixel++;
    236   ColorMapSize = 1 << BitsPerPixel;
    237   if (BitsPerPixel <= 1)
    238     InitCodeSize = 2;
    239   else
    240     InitCodeSize = BitsPerPixel;
    241   /*
    242    * Write the GIF header.
    243    * Note that we generate a plain GIF87 header for maximum compatibility.
    244    */
    245   putc('G', dinfo->pub.output_file);
    246   putc('I', dinfo->pub.output_file);
    247   putc('F', dinfo->pub.output_file);
    248   putc('8', dinfo->pub.output_file);
    249   putc('7', dinfo->pub.output_file);
    250   putc('a', dinfo->pub.output_file);
    251   /* Write the Logical Screen Descriptor */
    252   put_word(dinfo, (unsigned int) dinfo->cinfo->output_width);
    253   put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
    254   FlagByte = 0x80;              /* Yes, there is a global color table */
    255   FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
    256   FlagByte |= (BitsPerPixel-1); /* size of global color table */
    257   putc(FlagByte, dinfo->pub.output_file);
    258   putc(0, dinfo->pub.output_file); /* Background color index */
    259   putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */
    260   /* Write the Global Color Map */
    261   /* If the color map is more than 8 bits precision, */
    262   /* we reduce it to 8 bits by shifting */
    263   for (i=0; i < ColorMapSize; i++) {
    264     if (i < num_colors) {
    265       if (colormap != NULL) {
    266         if (dinfo->cinfo->out_color_space == JCS_RGB) {
    267           /* Normal case: RGB color map */
    268           putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file);
    269           putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file);
    270           putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file);
    271         } else {
    272           /* Grayscale "color map": possible if quantizing grayscale image */
    273           put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift);
    274         }
    275       } else {
    276         /* Create a grayscale map of num_colors values, range 0..255 */
    277         put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1));
    278       }
    279     } else {
    280       /* fill out the map to a power of 2 */
    281       put_3bytes(dinfo, 0);
    282     }
    283   }
    284   /* Write image separator and Image Descriptor */
    285   putc(',', dinfo->pub.output_file); /* separator */
    286   put_word(dinfo, 0);           /* left/top offset */
    287   put_word(dinfo, 0);
    288   put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */
    289   put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
    290   /* flag byte: not interlaced, no local color map */
    291   putc(0x00, dinfo->pub.output_file);
    292   /* Write Initial Code Size byte */
    293   putc(InitCodeSize, dinfo->pub.output_file);
    294 
    295   /* Initialize for "compression" of image data */
    296   compress_init(dinfo, InitCodeSize+1);
    297 }
    298 
    299 
    300 /*
    301  * Startup: write the file header.
    302  */
    303 
    304 METHODDEF(void)
    305 start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
    306 {
    307   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
    308 
    309   if (cinfo->quantize_colors)
    310     emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap);
    311   else
    312     emit_header(dest, 256, (JSAMPARRAY) NULL);
    313 }
    314 
    315 
    316 /*
    317  * Write some pixel data.
    318  * In this module rows_supplied will always be 1.
    319  */
    320 
    321 METHODDEF(void)
    322 put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
    323                 JDIMENSION rows_supplied)
    324 {
    325   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
    326   register JSAMPROW ptr;
    327   register JDIMENSION col;
    328 
    329   ptr = dest->pub.buffer[0];
    330   for (col = cinfo->output_width; col > 0; col--) {
    331     compress_pixel(dest, GETJSAMPLE(*ptr++));
    332   }
    333 }
    334 
    335 
    336 /*
    337  * Finish up at the end of the file.
    338  */
    339 
    340 METHODDEF(void)
    341 finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
    342 {
    343   gif_dest_ptr dest = (gif_dest_ptr) dinfo;
    344 
    345   /* Flush "compression" mechanism */
    346   compress_term(dest);
    347   /* Write a zero-length data block to end the series */
    348   putc(0, dest->pub.output_file);
    349   /* Write the GIF terminator mark */
    350   putc(';', dest->pub.output_file);
    351   /* Make sure we wrote the output file OK */
    352   fflush(dest->pub.output_file);
    353   if (ferror(dest->pub.output_file))
    354     ERREXIT(cinfo, JERR_FILE_WRITE);
    355 }
    356 
    357 
    358 /*
    359  * The module selection routine for GIF format output.
    360  */
    361 
    362 GLOBAL(djpeg_dest_ptr)
    363 jinit_write_gif (j_decompress_ptr cinfo)
    364 {
    365   gif_dest_ptr dest;
    366 
    367   /* Create module interface object, fill in method pointers */
    368   dest = (gif_dest_ptr)
    369       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    370                                   sizeof(gif_dest_struct));
    371   dest->cinfo = cinfo;          /* make back link for subroutines */
    372   dest->pub.start_output = start_output_gif;
    373   dest->pub.put_pixel_rows = put_pixel_rows;
    374   dest->pub.finish_output = finish_output_gif;
    375 
    376   if (cinfo->out_color_space != JCS_GRAYSCALE &&
    377       cinfo->out_color_space != JCS_RGB)
    378     ERREXIT(cinfo, JERR_GIF_COLORSPACE);
    379 
    380   /* Force quantization if color or if > 8 bits input */
    381   if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) {
    382     /* Force quantization to at most 256 colors */
    383     cinfo->quantize_colors = TRUE;
    384     if (cinfo->desired_number_of_colors > 256)
    385       cinfo->desired_number_of_colors = 256;
    386   }
    387 
    388   /* Calculate output image dimensions so we can allocate space */
    389   jpeg_calc_output_dimensions(cinfo);
    390 
    391   if (cinfo->output_components != 1) /* safety check: just one component? */
    392     ERREXIT(cinfo, JERR_GIF_BUG);
    393 
    394   /* Create decompressor output buffer. */
    395   dest->pub.buffer = (*cinfo->mem->alloc_sarray)
    396     ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1);
    397   dest->pub.buffer_height = 1;
    398 
    399   return (djpeg_dest_ptr) dest;
    400 }
    401 
    402 #endif /* GIF_SUPPORTED */
    403