1 const char deanimate_rcs[] = "$Id: deanimate.c,v 1.5 2001/09/10 10:16:06 oes 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 * IJBSWA 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.5 2001/09/10 10:16:06 oes
41 * Silenced compiler warnings
43 * Revision 1.4 2001/07/18 12:28:49 oes
44 * - Added feature for extracting the first frame
46 * - Separated image buffer extension into buf_extend
47 * - Extended gif deanimation to GIF87a (untested!)
50 * Revision 1.3 2001/07/15 13:57:50 jongfoster
51 * Adding #includes string.h and miscutil.h
53 * Revision 1.2 2001/07/13 13:46:20 oes
54 * Introduced GIF deanimation feature
57 **********************************************************************/
66 #include "deanimate.h"
69 const char deanimate_h_rcs[] = DEANIMATE_H_VERSION;
71 /*********************************************************************
75 * Description : Safely frees a struct binbuffer
78 * 1 : buf = Pointer to the binbuffer to be freed
82 *********************************************************************/
83 void buf_free(struct binbuffer *buf)
85 if (buf == NULL) return;
87 if (buf->buffer != NULL)
97 /*********************************************************************
99 * Function : buf_extend
101 * Description : Ensure that a given binbuffer can hold a given amount
102 * of bytes, by reallocating its buffer if necessary.
103 * Allocate new mem in chunks of 1000 bytes, so we don't
104 * have to realloc() too often.
107 * 1 : buf = Pointer to the binbuffer
108 * 2 : length = Desired minimum size
111 * Returns : 0 on success, 1 on failiure.
113 *********************************************************************/
114 int buf_extend(struct binbuffer *buf, size_t length)
118 if (buf->offset + length > buf->size)
120 buf->size = buf->size + length + 1000 - (buf->size + length) % 1000;
121 newbuf = (char *)realloc(buf->buffer, buf->size);
130 buf->buffer = newbuf;
139 /*********************************************************************
141 * Function : buf_copy
143 * Description : Safely copies a given amount of bytes from one
144 * struct binbuffer to another, advancing the
145 * offsets appropriately.
148 * 1 : src = Pointer to the source binbuffer
149 * 2 : dst = Pointer to the destination binbuffer
150 * 3 : length = Number of bytes to be copied
152 * Returns : 0 on success, 1 on failiure.
154 *********************************************************************/
155 int buf_copy(struct binbuffer *src, struct binbuffer *dst, size_t length)
159 * Sanity check: Can't copy more data than we have
161 if (src->offset + length > src->size)
167 * Ensure that dst can hold the new data
169 if (buf_extend(dst, length))
175 * Now that it's safe, memcpy() the desired amount of
176 * data from src to dst and adjust the offsets
178 memcpy(dst->buffer + dst->offset, src->buffer + src->offset, length);
179 src->offset += length;
180 dst->offset += length;
187 /*********************************************************************
189 * Function : buf_getbyte
191 * Description : Safely gets a byte from a given binbuffer at a
195 * 1 : buf = Pointer to the source binbuffer
196 * 2 : offset = Offset to the desired byte
198 * Returns : The byte on success, or 0 on failiure
200 *********************************************************************/
201 unsigned char buf_getbyte(struct binbuffer *src, int offset)
203 if (src->offset + offset < src->size)
205 return (unsigned char)*(src->buffer + src->offset + offset);
215 /*********************************************************************
217 * Function : gif_skip_data_block
219 * Description : Safely advances the offset of a given struct binbuffer
220 * that contains a GIF image and whose offset is
221 * positioned at the start of a data block, behind
225 * 1 : buf = Pointer to the binbuffer
227 * Returns : 0 on success, or 1 on failiure
229 *********************************************************************/
230 int gif_skip_data_block(struct binbuffer *buf)
235 * Data blocks are sequences of chunks, which are headed
236 * by a one-byte length field, with the last chunk having
239 while((c = buf_getbyte(buf, 0)))
241 if ((buf->offset += c + 1) >= buf->size - 1)
253 /*********************************************************************
255 * Function : gif_extract_image
257 * Description : Safely extracts an image data block from a given
258 * struct binbuffer that contains a GIF image and whose
259 * offset is positioned at the start of a data block
260 * into a given destination binbuffer.
263 * 1 : src = Pointer to the source binbuffer
264 * 2 : dst = Pointer to the destination binbuffer
266 * Returns : 0 on success, or 1 on failiure
268 *********************************************************************/
269 int gif_extract_image(struct binbuffer *src, struct binbuffer *dst)
274 * Remember the colormap flag and copy the image head
276 c = buf_getbyte(src, 9);
277 if (buf_copy(src, dst, 10))
283 * If the image has a local colormap, copy it.
287 if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
292 if (buf_copy(src, dst, 1)) return 1;
295 * Copy the image chunk by chunk.
297 while((c = buf_getbyte(src, 0)))
299 if (buf_copy(src, dst, (size_t) c + 1)) return 1;
301 if (buf_copy(src, dst, 1)) return 1;
304 * Trim and rewind the dst buffer
306 if (NULL == (dst->buffer = (char *)realloc(dst->buffer, (size_t) dst->offset))) return 1;
307 dst->size = dst->offset;
314 /*********************************************************************
316 * Function : gif_deanimate
318 * Description : Deanimate a given GIF image, i.e. given a GIF with
319 * an (optional) image block and an arbitrary number
320 * of image extension blocks, produce an output GIF with
321 * only one image block that contains the last image
322 * (extenstion) block of the original.
323 * Also strip Comments, Application extenstions, etc.
326 * 1 : src = Pointer to the source binbuffer
327 * 2 : dst = Pointer to the destination binbuffer
328 * 3 : get_first_image = Flag: If set, get the first image
329 * If unset (default), get the last
331 * Returns : 0 on success, or 1 on failiure
333 *********************************************************************/
334 int gif_deanimate(struct binbuffer *src, struct binbuffer *dst, int get_first_image)
337 struct binbuffer *image;
339 if (NULL == src || NULL == dst)
344 c = buf_getbyte(src, 10);
347 * Check & copy GIF header
349 if (strncmp(src->buffer, "GIF89a", 6) && strncmp(src->buffer, "GIF87a", 6))
355 if (buf_copy(src, dst, 13))
362 * Look for global colormap and copy if found.
366 if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
373 * Reserve a buffer for the current image block
375 if (NULL == (image = (struct binbuffer *)zalloc(sizeof(*image))))
381 * Parse the GIF block by block and copy the relevant
384 while(src->offset < src->size)
386 switch(buf_getbyte(src, 0))
389 * End-of-GIF Marker: Append current image and return
395 * Image block: Extract to current image buffer.
399 if (gif_extract_image(src, image)) goto failed;
400 if (get_first_image) goto write;
404 * Extension block: Look at next byte and decide
407 switch (buf_getbyte(src, 1))
410 * Image extension: Copy extension header and image
411 * to the current image buffer
415 if (buf_copy(src, image, 8) || buf_getbyte(src, 0) != 0x2c) goto failed;
416 if (gif_extract_image(src, image)) goto failed;
417 if (get_first_image) goto write;
421 * Application extension: Skip
424 if ((src->offset += 14) >= src->size || gif_skip_data_block(src)) goto failed;
428 * Comment extension: Skip
431 if ((src->offset += 2) >= src->size || gif_skip_data_block(src)) goto failed;
435 * Plain text extension: Skip
438 if ((src->offset += 15) >= src->size || gif_skip_data_block(src)) goto failed;
442 * Ooops, what type of extension is that?
450 * Ooops, what type of block is that?
456 } /* -END- while src */
459 * Either we got here by goto, or because the GIF is
460 * bogus and EOF was reached before an end-of-gif marker
469 * Append the current image to dst and return
473 if (buf_copy(image, dst, image->size)) goto failed;
474 if (buf_extend(dst, 1)) goto failed;
475 *(dst->buffer + dst->offset++) = 0x3b;