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