1 const char deanimate_rcs[] = "$Id: deanimate.c,v 1.23 2012/03/09 16:24:36 fabiankeil Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/deanimate.c,v $
6 * Purpose : Declares functions to manipulate binary images on the
7 * fly. High-level functions include:
8 * - Deanimation of GIF images
10 * Copyright : Written by and Copyright (C) 2001 - 2004, 2006 by the
11 * SourceForge Privoxy team. http://www.privoxy.org/
13 * Based on the GIF file format specification (see
14 * http://tronche.com/computer-graphics/gif/gif89a.html)
15 * and ideas from the Image::DeAnim Perl module by
16 * Ken MacFarlane, <ksm+cpan@universal.dca.net>
18 * This program is free software; you can redistribute it
19 * and/or modify it under the terms of the GNU General
20 * Public License as published by the Free Software
21 * Foundation; either version 2 of the License, or (at
22 * your option) any later version.
24 * This program is distributed in the hope that it will
25 * be useful, but WITHOUT ANY WARRANTY; without even the
26 * implied warranty of MERCHANTABILITY or FITNESS FOR A
27 * PARTICULAR PURPOSE. See the GNU General Public
28 * License for more details.
30 * The GNU General Public License should be included with
31 * this file. If not, you can view it at
32 * http://www.gnu.org/copyleft/gpl.html
33 * or write to the Free Software Foundation, Inc., 59
34 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 **********************************************************************/
46 #include "deanimate.h"
49 const char deanimate_h_rcs[] = DEANIMATE_H_VERSION;
51 /*********************************************************************
55 * Description : Safely frees a struct binbuffer
58 * 1 : buf = Pointer to the binbuffer to be freed
62 *********************************************************************/
63 void buf_free(struct binbuffer *buf)
65 if (buf == NULL) return;
67 if (buf->buffer != NULL)
77 /*********************************************************************
79 * Function : buf_extend
81 * Description : Ensure that a given binbuffer can hold a given amount
82 * of bytes, by reallocating its buffer if necessary.
83 * Allocate new mem in chunks of 1024 bytes, so we don't
84 * have to realloc() too often.
87 * 1 : buf = Pointer to the binbuffer
88 * 2 : length = Desired minimum size
91 * Returns : 0 on success, 1 on failure.
93 *********************************************************************/
94 static int buf_extend(struct binbuffer *buf, size_t length)
98 if (buf->offset + length > buf->size)
100 buf->size = ((buf->size + length + (size_t)1023) & ~(size_t)1023);
101 newbuf = (char *)realloc(buf->buffer, buf->size);
110 buf->buffer = newbuf;
119 /*********************************************************************
121 * Function : buf_copy
123 * Description : Safely copies a given amount of bytes from one
124 * struct binbuffer to another, advancing the
125 * offsets appropriately.
128 * 1 : src = Pointer to the source binbuffer
129 * 2 : dst = Pointer to the destination binbuffer
130 * 3 : length = Number of bytes to be copied
132 * Returns : 0 on success, 1 on failure.
134 *********************************************************************/
135 static int buf_copy(struct binbuffer *src, struct binbuffer *dst, size_t length)
139 * Sanity check: Can't copy more data than we have
141 if (src->offset + length > src->size)
147 * Ensure that dst can hold the new data
149 if (buf_extend(dst, length))
155 * Now that it's safe, memcpy() the desired amount of
156 * data from src to dst and adjust the offsets
158 memcpy(dst->buffer + dst->offset, src->buffer + src->offset, length);
159 src->offset += length;
160 dst->offset += length;
167 /*********************************************************************
169 * Function : buf_getbyte
171 * Description : Safely gets a byte from a given binbuffer at a
175 * 1 : src = Pointer to the source binbuffer
176 * 2 : offset = Offset to the desired byte
178 * Returns : The byte on success, or 0 on failure
180 *********************************************************************/
181 static unsigned char buf_getbyte(const struct binbuffer *src, size_t offset)
183 if (src->offset + offset < src->size)
185 return (unsigned char)*(src->buffer + src->offset + offset);
195 /*********************************************************************
197 * Function : gif_skip_data_block
199 * Description : Safely advances the offset of a given struct binbuffer
200 * that contains a GIF image and whose offset is
201 * positioned at the start of a data block, behind
205 * 1 : buf = Pointer to the binbuffer
207 * Returns : 0 on success, or 1 on failure
209 *********************************************************************/
210 static int gif_skip_data_block(struct binbuffer *buf)
215 * Data blocks are sequences of chunks, which are headed
216 * by a one-byte length field, with the last chunk having
219 while((c = buf_getbyte(buf, 0)) != '\0')
221 buf->offset += (size_t)c + 1;
222 if (buf->offset >= buf->size - 1)
234 /*********************************************************************
236 * Function : gif_extract_image
238 * Description : Safely extracts an image data block from a given
239 * struct binbuffer that contains a GIF image and whose
240 * offset is positioned at the start of a data block
241 * into a given destination binbuffer.
244 * 1 : src = Pointer to the source binbuffer
245 * 2 : dst = Pointer to the destination binbuffer
247 * Returns : 0 on success, or 1 on failure
249 *********************************************************************/
250 static int gif_extract_image(struct binbuffer *src, struct binbuffer *dst)
255 * Remember the colormap flag and copy the image head
257 c = buf_getbyte(src, 9);
258 if (buf_copy(src, dst, 10))
264 * If the image has a local colormap, copy it.
268 int map_length = 3 * (1 << ((c & 0x07) + 1));
271 log_error(LOG_LEVEL_DEANIMATE,
272 "colormap length = %d (%c)?", map_length, c);
275 if (buf_copy(src, dst, (size_t)map_length))
280 if (buf_copy(src, dst, 1)) return 1;
283 * Copy the image chunk by chunk.
285 while((c = buf_getbyte(src, 0)) != '\0')
287 if (buf_copy(src, dst, 1 + (size_t) c)) return 1;
289 if (buf_copy(src, dst, 1)) return 1;
292 * Trim and rewind the dst buffer
294 if (NULL == (dst->buffer = (char *)realloc(dst->buffer, dst->offset))) return 1;
295 dst->size = dst->offset;
302 /*********************************************************************
304 * Function : gif_deanimate
306 * Description : Deanimate a given GIF image, i.e. given a GIF with
307 * an (optional) image block and an arbitrary number
308 * of image extension blocks, produce an output GIF with
309 * only one image block that contains the last image
310 * (extenstion) block of the original.
311 * Also strip Comments, Application extenstions, etc.
314 * 1 : src = Pointer to the source binbuffer
315 * 2 : dst = Pointer to the destination binbuffer
316 * 3 : get_first_image = Flag: If set, get the first image
317 * If unset (default), get the last
319 * Returns : 0 on success, or 1 on failure
321 *********************************************************************/
322 int gif_deanimate(struct binbuffer *src, struct binbuffer *dst, int get_first_image)
325 struct binbuffer *image;
327 if (NULL == src || NULL == dst)
332 c = buf_getbyte(src, 10);
335 * Check & copy GIF header
337 if (strncmp(src->buffer, "GIF89a", 6) && strncmp(src->buffer, "GIF87a", 6))
343 if (buf_copy(src, dst, 13))
350 * Look for global colormap and copy if found.
354 int map_length = 3 * (1 << ((c & 0x07) + 1));
357 log_error(LOG_LEVEL_DEANIMATE,
358 "colormap length = %d (%c)?", map_length, c);
361 if (buf_copy(src, dst, (size_t)map_length))
368 * Reserve a buffer for the current image block
370 image = zalloc_or_die(sizeof(*image));
373 * Parse the GIF block by block and copy the relevant
376 while(src->offset < src->size)
378 switch(buf_getbyte(src, 0))
381 * End-of-GIF Marker: Append current image and return
387 * Image block: Extract to current image buffer.
391 if (gif_extract_image(src, image)) goto failed;
392 if (get_first_image) goto write;
396 * Extension block: Look at next byte and decide
399 switch (buf_getbyte(src, 1))
402 * Image extension: Copy extension header and image
403 * to the current image buffer
407 if (buf_copy(src, image, 8) || buf_getbyte(src, 0) != 0x2c) goto failed;
408 if (gif_extract_image(src, image)) goto failed;
409 if (get_first_image) goto write;
413 * Application extension: Skip
416 if ((src->offset += 14) >= src->size || gif_skip_data_block(src)) goto failed;
420 * Comment extension: Skip
423 if ((src->offset += 2) >= src->size || gif_skip_data_block(src)) goto failed;
427 * Plain text extension: Skip
430 if ((src->offset += 15) >= src->size || gif_skip_data_block(src)) goto failed;
434 * Ooops, what type of extension is that?
442 * Ooops, what type of block is that?
448 } /* -END- while src */
451 * Either we got here by goto, or because the GIF is
452 * bogus and EOF was reached before an end-of-gif marker
461 * Append the current image to dst and return
465 if (buf_copy(image, dst, image->size)) goto failed;
466 if (buf_extend(dst, 1)) goto failed;
467 *(dst->buffer + dst->offset++) = 0x3b;