1 const char deanimate_rcs[] = "$Id: deanimate.c,v 1.9 2002/03/13 00:27:04 jongfoster Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/deanimate.c,v $
6 * Purpose : Declares functions to deanimate GIF images on the fly.
8 * Functions declared include: gif_deanimate, buf_free,
9 * buf_copy, buf_getbyte, gif_skip_data_block, and
12 * Copyright : Written by and Copyright (C) 2001 by the the SourceForge
13 * Privoxy team. http://ijbswa.sourceforge.net
15 * Based on the GIF file format specification (see
16 * http://tronche.com/computer-graphics/gif/gif89a.html)
17 * and ideas from the Image::DeAnim Perl module by
18 * Ken MacFarlane, <ksm+cpan@universal.dca.net>
20 * This program is free software; you can redistribute it
21 * and/or modify it under the terms of the GNU General
22 * Public License as published by the Free Software
23 * Foundation; either version 2 of the License, or (at
24 * your option) any later version.
26 * This program is distributed in the hope that it will
27 * be useful, but WITHOUT ANY WARRANTY; without even the
28 * implied warranty of MERCHANTABILITY or FITNESS FOR A
29 * PARTICULAR PURPOSE. See the GNU General Public
30 * License for more details.
32 * The GNU General Public License should be included with
33 * this file. If not, you can view it at
34 * http://www.gnu.org/copyleft/gpl.html
35 * or write to the Free Software Foundation, Inc., 59
36 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 * $Log: deanimate.c,v $
40 * Revision 1.9 2002/03/13 00:27:04 jongfoster
43 * Revision 1.8 2002/03/09 19:42:47 jongfoster
44 * Fixing more warnings
46 * Revision 1.7 2002/03/08 17:46:04 jongfoster
47 * Fixing int/size_t warnings
49 * Revision 1.6 2002/03/07 03:46:17 oes
50 * Fixed compiler warnings
52 * Revision 1.5 2001/09/10 10:16:06 oes
53 * Silenced compiler warnings
55 * Revision 1.4 2001/07/18 12:28:49 oes
56 * - Added feature for extracting the first frame
58 * - Separated image buffer extension into buf_extend
59 * - Extended gif deanimation to GIF87a (untested!)
62 * Revision 1.3 2001/07/15 13:57:50 jongfoster
63 * Adding #includes string.h and miscutil.h
65 * Revision 1.2 2001/07/13 13:46:20 oes
66 * Introduced GIF deanimation feature
69 **********************************************************************/
78 #include "deanimate.h"
81 const char deanimate_h_rcs[] = DEANIMATE_H_VERSION;
83 /*********************************************************************
87 * Description : Safely frees a struct binbuffer
90 * 1 : buf = Pointer to the binbuffer to be freed
94 *********************************************************************/
95 void buf_free(struct binbuffer *buf)
97 if (buf == NULL) return;
99 if (buf->buffer != NULL)
109 /*********************************************************************
111 * Function : buf_extend
113 * Description : Ensure that a given binbuffer can hold a given amount
114 * of bytes, by reallocating its buffer if necessary.
115 * Allocate new mem in chunks of 1024 bytes, so we don't
116 * have to realloc() too often.
119 * 1 : buf = Pointer to the binbuffer
120 * 2 : length = Desired minimum size
123 * Returns : 0 on success, 1 on failiure.
125 *********************************************************************/
126 int buf_extend(struct binbuffer *buf, size_t length)
130 if (buf->offset + length > buf->size)
132 buf->size = ((buf->size + length + (size_t)1023) & ~(size_t)1023);
133 newbuf = (char *)realloc(buf->buffer, buf->size);
142 buf->buffer = newbuf;
151 /*********************************************************************
153 * Function : buf_copy
155 * Description : Safely copies a given amount of bytes from one
156 * struct binbuffer to another, advancing the
157 * offsets appropriately.
160 * 1 : src = Pointer to the source binbuffer
161 * 2 : dst = Pointer to the destination binbuffer
162 * 3 : length = Number of bytes to be copied
164 * Returns : 0 on success, 1 on failiure.
166 *********************************************************************/
167 int buf_copy(struct binbuffer *src, struct binbuffer *dst, size_t length)
171 * Sanity check: Can't copy more data than we have
173 if (src->offset + length > src->size)
179 * Ensure that dst can hold the new data
181 if (buf_extend(dst, length))
187 * Now that it's safe, memcpy() the desired amount of
188 * data from src to dst and adjust the offsets
190 memcpy(dst->buffer + dst->offset, src->buffer + src->offset, length);
191 src->offset += length;
192 dst->offset += length;
199 /*********************************************************************
201 * Function : buf_getbyte
203 * Description : Safely gets a byte from a given binbuffer at a
207 * 1 : buf = Pointer to the source binbuffer
208 * 2 : offset = Offset to the desired byte
210 * Returns : The byte on success, or 0 on failiure
212 *********************************************************************/
213 unsigned char buf_getbyte(struct binbuffer *src, size_t offset)
215 if (src->offset + offset < src->size)
217 return (unsigned char)*(src->buffer + src->offset + offset);
227 /*********************************************************************
229 * Function : gif_skip_data_block
231 * Description : Safely advances the offset of a given struct binbuffer
232 * that contains a GIF image and whose offset is
233 * positioned at the start of a data block, behind
237 * 1 : buf = Pointer to the binbuffer
239 * Returns : 0 on success, or 1 on failiure
241 *********************************************************************/
242 int gif_skip_data_block(struct binbuffer *buf)
247 * Data blocks are sequences of chunks, which are headed
248 * by a one-byte length field, with the last chunk having
251 while((c = buf_getbyte(buf, 0)) != '\0')
253 if ((buf->offset += c + 1) >= buf->size - 1)
265 /*********************************************************************
267 * Function : gif_extract_image
269 * Description : Safely extracts an image data block from a given
270 * struct binbuffer that contains a GIF image and whose
271 * offset is positioned at the start of a data block
272 * into a given destination binbuffer.
275 * 1 : src = Pointer to the source binbuffer
276 * 2 : dst = Pointer to the destination binbuffer
278 * Returns : 0 on success, or 1 on failiure
280 *********************************************************************/
281 int gif_extract_image(struct binbuffer *src, struct binbuffer *dst)
286 * Remember the colormap flag and copy the image head
288 c = buf_getbyte(src, 9);
289 if (buf_copy(src, dst, 10))
295 * If the image has a local colormap, copy it.
299 if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
304 if (buf_copy(src, dst, 1)) return 1;
307 * Copy the image chunk by chunk.
309 while((c = buf_getbyte(src, 0)) != '\0')
311 if (buf_copy(src, dst, 1 + (size_t) c)) return 1;
313 if (buf_copy(src, dst, 1)) return 1;
316 * Trim and rewind the dst buffer
318 if (NULL == (dst->buffer = (char *)realloc(dst->buffer, dst->offset))) return 1;
319 dst->size = dst->offset;
326 /*********************************************************************
328 * Function : gif_deanimate
330 * Description : Deanimate a given GIF image, i.e. given a GIF with
331 * an (optional) image block and an arbitrary number
332 * of image extension blocks, produce an output GIF with
333 * only one image block that contains the last image
334 * (extenstion) block of the original.
335 * Also strip Comments, Application extenstions, etc.
338 * 1 : src = Pointer to the source binbuffer
339 * 2 : dst = Pointer to the destination binbuffer
340 * 3 : get_first_image = Flag: If set, get the first image
341 * If unset (default), get the last
343 * Returns : 0 on success, or 1 on failiure
345 *********************************************************************/
346 int gif_deanimate(struct binbuffer *src, struct binbuffer *dst, int get_first_image)
349 struct binbuffer *image;
351 if (NULL == src || NULL == dst)
356 c = buf_getbyte(src, 10);
359 * Check & copy GIF header
361 if (strncmp(src->buffer, "GIF89a", 6) && strncmp(src->buffer, "GIF87a", 6))
367 if (buf_copy(src, dst, 13))
374 * Look for global colormap and copy if found.
378 if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
385 * Reserve a buffer for the current image block
387 if (NULL == (image = (struct binbuffer *)zalloc(sizeof(*image))))
393 * Parse the GIF block by block and copy the relevant
396 while(src->offset < src->size)
398 switch(buf_getbyte(src, 0))
401 * End-of-GIF Marker: Append current image and return
407 * Image block: Extract to current image buffer.
411 if (gif_extract_image(src, image)) goto failed;
412 if (get_first_image) goto write;
416 * Extension block: Look at next byte and decide
419 switch (buf_getbyte(src, 1))
422 * Image extension: Copy extension header and image
423 * to the current image buffer
427 if (buf_copy(src, image, 8) || buf_getbyte(src, 0) != 0x2c) goto failed;
428 if (gif_extract_image(src, image)) goto failed;
429 if (get_first_image) goto write;
433 * Application extension: Skip
436 if ((src->offset += 14) >= src->size || gif_skip_data_block(src)) goto failed;
440 * Comment extension: Skip
443 if ((src->offset += 2) >= src->size || gif_skip_data_block(src)) goto failed;
447 * Plain text extension: Skip
450 if ((src->offset += 15) >= src->size || gif_skip_data_block(src)) goto failed;
454 * Ooops, what type of extension is that?
462 * Ooops, what type of block is that?
468 } /* -END- while src */
471 * Either we got here by goto, or because the GIF is
472 * bogus and EOF was reached before an end-of-gif marker
481 * Append the current image to dst and return
485 if (buf_copy(image, dst, image->size)) goto failed;
486 if (buf_extend(dst, 1)) goto failed;
487 *(dst->buffer + dst->offset++) = 0x3b;