1 /* gifread.c - Functions to read GIFs.
2 Copyright (C) 1997-9 Eddie Kohler, eddietwo@lcs.mit.edu
3 This file is part of the GIF library.
4
5 The GIF library is free software*. It is distributed under the GNU General
6 Public License, version 2 or later; you can copy, distribute, or alter it
7 at will, as long as this notice is kept intact and this source code is made
8 available. There is no warranty, express or implied.
9
10 *The LZW compression method used by GIFs is patented. Unisys, the patent
11 holder, allows the compression algorithm to be used without a license in
12 software distributed at no cost to the user. */
13
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #elif !defined(__cplusplus)
17 /* Assume we don't have inline by default */
18 # define inline
19 #endif
20 #include "gif.h"
21 #include <stdarg.h>
22 #include <assert.h>
23 #include <string.h>
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 typedef struct {
29
30 Gif_Stream *stream;
31
32 Gif_Code *prefix;
33 byte *suffix;
34 u_int16_t *length;
35
36 u_int16_t width;
37 u_int16_t height;
38
39 byte *image;
40 byte *maximage;
41
42 unsigned decodepos;
43
44 Gif_ReadErrorHandler handler;
45 void *handler_thunk;
46
47 } Gif_Context;
48
49
50 typedef struct Gif_Reader {
51
52 FILE *f;
53 const byte *v;
54 u_int32_t w;
55 u_int32_t length;
56 int is_record;
57 int is_eoi;
58 byte (*byte_getter)(struct Gif_Reader *);
59 void (*block_getter)(byte *, u_int32_t, struct Gif_Reader *);
60 u_int32_t (*offseter)(struct Gif_Reader *);
61 int (*eofer)(struct Gif_Reader *);
62
63 } Gif_Reader;
64
65
66 #define gifgetc(grr) ((char)(*grr->byte_getter)(grr))
67 #define gifgetbyte(grr) ((*grr->byte_getter)(grr))
68 #define gifgetblock(ptr, size, grr) ((*grr->block_getter)(ptr, size, grr))
69 #define gifgetoffset(grr) ((*grr->offseter)(grr))
70 #define gifeof(grr) ((*grr->eofer)(grr))
71
72 static inline u_int16_t
gifgetunsigned(Gif_Reader * grr)73 gifgetunsigned(Gif_Reader *grr)
74 {
75 byte one = gifgetbyte(grr);
76 byte two = gifgetbyte(grr);
77 return one | (two << 8);
78 }
79
80
81 static byte
file_byte_getter(Gif_Reader * grr)82 file_byte_getter(Gif_Reader *grr)
83 {
84 int i = getc(grr->f);
85 return i == EOF ? 0 : (byte)i;
86 }
87
88 static void
file_block_getter(byte * p,u_int32_t s,Gif_Reader * grr)89 file_block_getter(byte *p, u_int32_t s, Gif_Reader *grr)
90 {
91 fread(p, 1, s, grr->f);
92 }
93
94 static u_int32_t
file_offseter(Gif_Reader * grr)95 file_offseter(Gif_Reader *grr)
96 {
97 return ftell(grr->f);
98 }
99
100 static int
file_eofer(Gif_Reader * grr)101 file_eofer(Gif_Reader *grr)
102 {
103 return feof(grr->f);
104 }
105
106
107 static byte
record_byte_getter(Gif_Reader * grr)108 record_byte_getter(Gif_Reader *grr)
109 {
110 return grr->w ? (grr->w--, *grr->v++) : 0;
111 }
112
113 static void
record_block_getter(byte * p,u_int32_t s,Gif_Reader * grr)114 record_block_getter(byte *p, u_int32_t s, Gif_Reader *grr)
115 {
116 if (s > grr->w) s = grr->w;
117 memcpy(p, grr->v, s);
118 grr->w -= s, grr->v += s;
119 }
120
121 static u_int32_t
record_offseter(Gif_Reader * grr)122 record_offseter(Gif_Reader *grr)
123 {
124 return grr->length - grr->w;
125 }
126
127 static int
record_eofer(Gif_Reader * grr)128 record_eofer(Gif_Reader *grr)
129 {
130 return grr->w == 0;
131 }
132
133
134 static void
make_data_reader(Gif_Reader * grr,const byte * data,u_int32_t length)135 make_data_reader(Gif_Reader *grr, const byte *data, u_int32_t length)
136 {
137 grr->v = data;
138 grr->length = length;
139 grr->w = length;
140 grr->is_record = 1;
141 grr->byte_getter = record_byte_getter;
142 grr->block_getter = record_block_getter;
143 grr->offseter = record_offseter;
144 grr->eofer = record_eofer;
145 }
146
147
148 static void
gif_read_error(Gif_Context * gfc,const char * error)149 gif_read_error(Gif_Context *gfc, const char *error)
150 {
151 gfc->stream->errors++;
152 if (gfc->handler)
153 gfc->handler(error, gfc->stream->nimages, gfc->handler_thunk);
154 }
155
156
157 static byte
one_code(Gif_Context * gfc,Gif_Code code)158 one_code(Gif_Context *gfc, Gif_Code code)
159 {
160 byte *suffixes = gfc->suffix;
161 Gif_Code *prefixes = gfc->prefix;
162 byte *ptr;
163 int lastsuffix;
164 u_int16_t codelength = gfc->length[code];
165
166 gfc->decodepos += codelength;
167 ptr = gfc->image + gfc->decodepos;
168 if (ptr > gfc->maximage || !codelength) {
169 gif_read_error(gfc, (!codelength ? "bad code" : "too much image data"));
170 /* 5/26/98 It's not good enough simply to count an error, because in the
171 read_image_data function, if code == next_code, we will store a byte in
172 gfc->image[gfc->decodepos-1]. Thus, fix decodepos so it's w/in the
173 image. */
174 gfc->decodepos = gfc->maximage - gfc->image;
175 return 0;
176 }
177
178 /* codelength will always be greater than 0. */
179 do {
180 lastsuffix = suffixes[code];
181 *--ptr = lastsuffix;
182 code = prefixes[code];
183 } while (--codelength > 0);
184
185 /* return the first pixel in the code, which, since we walked backwards
186 through the code, was the last suffix we processed. */
187 return lastsuffix;
188 }
189
190 static int
read_image_block(Gif_Reader * grr,byte * buffer,int * bit_pos_store,int * bit_len_store,int bits_needed)191 read_image_block(Gif_Reader *grr, byte *buffer, int *bit_pos_store,
192 int *bit_len_store, int bits_needed)
193 {
194 int bit_position = *bit_pos_store;
195 int bit_length = *bit_len_store;
196 byte block_len;
197
198 while (bit_position + bits_needed > bit_length) {
199 /* Read in the next data block. */
200 if (bit_position >= 8) {
201 /* Need to shift down the upper, unused part of `buffer' */
202 int i = bit_position / 8;
203 buffer[0] = buffer[i];
204 buffer[1] = buffer[i+1];
205 bit_position -= i * 8;
206 bit_length -= i * 8;
207 }
208 block_len = gifgetbyte(grr);
209 GIF_DEBUG(("\nimage_block(%d)", block_len));
210 if (block_len == 0) return 0;
211 gifgetblock(buffer + bit_length / 8, block_len, grr);
212 bit_length += block_len * 8;
213 }
214
215 *bit_pos_store = bit_position;
216 *bit_len_store = bit_length;
217 return 1;
218 }
219
220
221 static void
read_image_data(Gif_Context * gfc,Gif_Reader * grr)222 read_image_data(Gif_Context *gfc, Gif_Reader *grr)
223 {
224 /* we need a bit more than GIF_MAX_BLOCK in case a single code is split
225 across blocks */
226 byte buffer[GIF_MAX_BLOCK + 5];
227 int i;
228 u_int32_t accum;
229
230 int bit_position;
231 int bit_length;
232
233 Gif_Code code;
234 Gif_Code old_code;
235 Gif_Code clear_code;
236 Gif_Code eoi_code;
237 Gif_Code next_code;
238 #define CUR_BUMP_CODE (1 << bits_needed)
239 #define CUR_CODE_MASK ((1 << bits_needed) - 1)
240
241 int min_code_size;
242 int bits_needed;
243
244 gfc->decodepos = 0;
245
246 min_code_size = gifgetbyte(grr);
247 GIF_DEBUG(("\n\nmin_code_size(%d)", min_code_size));
248 if (min_code_size >= GIF_MAX_CODE_BITS) {
249 gif_read_error(gfc, "min_code_size too big");
250 min_code_size = GIF_MAX_CODE_BITS - 1;
251 } else if (min_code_size < 2) {
252 gif_read_error(gfc, "min_code_size too small");
253 min_code_size = 2;
254 }
255 clear_code = 1 << min_code_size;
256 for (code = 0; code < clear_code; code++) {
257 gfc->prefix[code] = 49428;
258 gfc->suffix[code] = (byte)code;
259 gfc->length[code] = 1;
260 }
261 eoi_code = clear_code + 1;
262
263 next_code = eoi_code;
264 bits_needed = min_code_size + 1;
265
266 code = clear_code;
267
268 bit_length = bit_position = 0;
269 /* Thus the `Read in the next data block.' code below will be invoked on the
270 first time through: exactly right! */
271
272 while (1) {
273
274 old_code = code;
275
276 /* GET A CODE INTO THE `code' VARIABLE.
277 *
278 * 9.Dec.1998 - Rather than maintain a byte pointer and a bit offset into
279 * the current byte (and the processing associated with that), we maintain
280 * one number: the offset, in bits, from the beginning of `buffer'. This
281 * much cleaner choice was inspired by Patrick J. Naughton
282 * <naughton@wind.sun.com>'s GIF-reading code, which does the same thing.
283 * His code distributed as part of XV in xvgif.c. */
284
285 if (bit_position + bits_needed > bit_length)
286 /* Read in the next data block. */
287 if (!read_image_block(grr, buffer, &bit_position, &bit_length,
288 bits_needed))
289 goto zero_length_block;
290
291 i = bit_position / 8;
292 accum = buffer[i] + (buffer[i+1] << 8);
293 if (bits_needed >= 8)
294 accum |= (buffer[i+2]) << 16;
295 code = (Gif_Code)((accum >> (bit_position % 8)) & CUR_CODE_MASK);
296 bit_position += bits_needed;
297
298 GIF_DEBUG(("%d", code));
299
300 /* CHECK FOR SPECIAL OR BAD CODES: clear_code, eoi_code, or a code that is
301 * too large. */
302 if (code == clear_code) {
303 bits_needed = min_code_size + 1;
304 next_code = eoi_code;
305 continue;
306
307 } else if (code == eoi_code)
308 break;
309
310 else if (code > next_code && next_code) {
311 /* code > next_code: a (hopefully recoverable) error.
312
313 Bug fix, 5/27: Do this even if old_code == clear_code, and set code
314 to 0 to prevent errors later. (If we didn't zero code, we'd later set
315 old_code = code; then we had old_code >= next_code; so the prefixes
316 array got all screwed up!) */
317 gif_read_error(gfc, "unexpected code");
318 code = 0;
319 }
320
321 /* PROCESS THE CURRENT CODE and define the next code. If no meaningful
322 * next code should be defined, then we have set next_code to either
323 * `eoi_code' or `clear_code' -- so we'll store useless prefix/suffix data
324 * in a useless place. */
325
326 /* *First,* set up the prefix and length for the next code
327 (in case code == next_code). */
328 gfc->prefix[next_code] = old_code;
329 gfc->length[next_code] = gfc->length[old_code] + 1;
330
331 /* Use one_code to process code. It's nice that it returns the first
332 pixel in code: that's what we need. */
333 gfc->suffix[next_code] = one_code(gfc, code);
334
335 /* Special processing if code == next_code: we didn't know code's final
336 suffix when we called one_code, but we do now. */
337 if (code == next_code)
338 gfc->image[gfc->decodepos - 1] = gfc->suffix[next_code];
339
340 /* Increment next_code except for the `clear_code' special case (that's
341 when we're reading at the end of a GIF) */
342 if (next_code != clear_code) {
343 next_code++;
344 if (next_code == CUR_BUMP_CODE) {
345 if (bits_needed < GIF_MAX_CODE_BITS)
346 bits_needed++;
347 else
348 next_code = clear_code;
349 }
350 }
351
352 }
353
354 /* read blocks until zero-length reached. */
355 i = gifgetbyte(grr);
356 GIF_DEBUG(("\nafter_image(%d)\n", i));
357 while (i > 0) {
358 gifgetblock(buffer, i, grr);
359 i = gifgetbyte(grr);
360 GIF_DEBUG(("\nafter_image(%d)\n", i));
361 }
362
363 /* zero-length block reached. */
364 zero_length_block:
365
366 if (gfc->image + gfc->decodepos < gfc->maximage)
367 gif_read_error(gfc, "not enough image data for image size");
368 else if (gfc->image + gfc->decodepos > gfc->maximage)
369 gif_read_error(gfc, "too much image data for image size");
370 }
371
372
373 static Gif_Colormap *
read_color_table(int size,Gif_Reader * grr)374 read_color_table(int size, Gif_Reader *grr)
375 {
376 Gif_Colormap *gfcm = Gif_NewFullColormap(size, size);
377 Gif_Color *c;
378 if (!gfcm) return 0;
379
380 GIF_DEBUG(("colormap(%d)", size));
381 for (c = gfcm->col; size; size--, c++) {
382 c->red = gifgetbyte(grr);
383 c->green = gifgetbyte(grr);
384 c->blue = gifgetbyte(grr);
385 c->haspixel = 0;
386 }
387
388 return gfcm;
389 }
390
391
392 static int
read_logical_screen_descriptor(Gif_Stream * gfs,Gif_Reader * grr)393 read_logical_screen_descriptor(Gif_Stream *gfs, Gif_Reader *grr)
394 /* returns 0 on memory error */
395 {
396 byte packed;
397
398 /* we don't care about logical screen width or height */
399 gfs->screen_width = gifgetunsigned(grr);
400 gfs->screen_height = gifgetunsigned(grr);
401
402 packed = gifgetbyte(grr);
403 gfs->background = gifgetbyte(grr);
404
405 /* don't care about pixel aspect ratio */
406 gifgetbyte(grr);
407
408 if (packed & 0x80) { /* have a global color table */
409 int ncol = 1 << ((packed & 0x07) + 1);
410 gfs->global = read_color_table(ncol, grr);
411 if (!gfs->global) return 0;
412 gfs->global->refcount = 1;
413 }
414
415 return 1;
416 }
417
418
419 static int
read_compressed_image(Gif_Image * gfi,Gif_Reader * grr,int read_flags)420 read_compressed_image(Gif_Image *gfi, Gif_Reader *grr, int read_flags)
421 {
422 if (grr->is_record) {
423 const byte *first = grr->v;
424 u_int32_t pos;
425
426 /* scan over image */
427 pos = 1; /* skip min code size */
428 while (pos < grr->w) {
429 int amt = grr->v[pos];
430 pos += amt + 1;
431 if (amt == 0) break;
432 }
433 if (pos > grr->w) pos = grr->w;
434
435 gfi->compressed_len = pos;
436 if (read_flags & GIF_READ_CONST_RECORD) {
437 gfi->compressed = (byte *)first;
438 gfi->free_compressed = 0;
439 } else {
440 gfi->compressed = Gif_NewArray(byte, gfi->compressed_len);
441 gfi->free_compressed = Gif_DeleteArrayFunc;
442 if (!gfi->compressed) return 0;
443 memcpy(gfi->compressed, first, gfi->compressed_len);
444 }
445
446 /* move reader over that image */
447 grr->v += pos;
448 grr->w -= pos;
449
450 } else {
451 /* non-record; have to read it block by block. */
452 u_int32_t comp_cap = 1024;
453 u_int32_t comp_len;
454 byte *comp = Gif_NewArray(byte, comp_cap);
455 int i;
456 if (!comp) return 0;
457
458 /* min code size */
459 i = gifgetbyte(grr);
460 comp[0] = i;
461 comp_len = 1;
462
463 i = gifgetbyte(grr);
464 while (i > 0) {
465 /* add 2 before check so we don't have to check after loop when appending
466 0 block */
467 if (comp_len + i + 2 > comp_cap) {
468 comp_cap *= 2;
469 Gif_ReArray(comp, byte, comp_cap);
470 if (!comp) return 0;
471 }
472 comp[comp_len] = i;
473 gifgetblock(comp + comp_len + 1, i, grr);
474 comp_len += i + 1;
475 i = gifgetbyte(grr);
476 }
477 comp[comp_len++] = 0;
478
479 gfi->compressed = comp;
480 gfi->compressed_len = comp_len;
481 gfi->free_compressed = Gif_DeleteArrayFunc;
482 }
483
484 return 1;
485 }
486
487
488 static int
uncompress_image(Gif_Context * gfc,Gif_Image * gfi,Gif_Reader * grr)489 uncompress_image(Gif_Context *gfc, Gif_Image *gfi, Gif_Reader *grr)
490 {
491 if (!Gif_CreateUncompressedImage(gfi)) return 0;
492 gfc->width = gfi->width;
493 gfc->height = gfi->height;
494 gfc->image = gfi->image_data;
495 gfc->maximage = gfi->image_data + gfi->width * gfi->height;
496 read_image_data(gfc, grr);
497 return 1;
498 }
499
500
501 int
Gif_FullUncompressImage(Gif_Image * gfi,Gif_ReadErrorHandler h,void * hthunk)502 Gif_FullUncompressImage(Gif_Image *gfi, Gif_ReadErrorHandler h, void *hthunk)
503 {
504 Gif_Context gfc;
505 Gif_Stream fake_gfs;
506 Gif_Reader grr;
507 int ok = 0;
508
509 /* return right away if image is already uncompressed. this might screw over
510 people who expect re-uncompressing to restore the compressed version. */
511 if (gfi->img)
512 return 1;
513 if (gfi->image_data)
514 /* we have uncompressed data, but not an `img' array;
515 this shouldn't happen */
516 return 0;
517
518 fake_gfs.errors = 0;
519 gfc.stream = &fake_gfs;
520 gfc.prefix = Gif_NewArray(Gif_Code, GIF_MAX_CODE);
521 gfc.suffix = Gif_NewArray(byte, GIF_MAX_CODE);
522 gfc.length = Gif_NewArray(u_int16_t, GIF_MAX_CODE);
523 gfc.handler = h;
524 gfc.handler_thunk = hthunk;
525
526 if (gfi && gfc.prefix && gfc.suffix && gfc.length && gfi->compressed) {
527 make_data_reader(&grr, gfi->compressed, gfi->compressed_len);
528 ok = uncompress_image(&gfc, gfi, &grr);
529 }
530
531 Gif_DeleteArray(gfc.prefix);
532 Gif_DeleteArray(gfc.suffix);
533 Gif_DeleteArray(gfc.length);
534 return ok && !fake_gfs.errors;
535 }
536
537
538 static int
read_image(Gif_Reader * grr,Gif_Context * gfc,Gif_Image * gfi,int read_flags)539 read_image(Gif_Reader *grr, Gif_Context *gfc, Gif_Image *gfi, int read_flags)
540 /* returns 0 on memory error */
541 {
542 byte packed;
543
544 gfi->left = gifgetunsigned(grr);
545 gfi->top = gifgetunsigned(grr);
546 gfi->width = gifgetunsigned(grr);
547 gfi->height = gifgetunsigned(grr);
548 packed = gifgetbyte(grr);
549 GIF_DEBUG(("<%ux%u>", gfi->width, gfi->height));
550
551 if (packed & 0x80) { /* have a local color table */
552 int ncol = 1 << ((packed & 0x07) + 1);
553 gfi->local = read_color_table(ncol, grr);
554 if (!gfi->local) return 0;
555 gfi->local->refcount = 1;
556 }
557
558 gfi->interlace = (packed & 0x40) != 0;
559
560 /* Keep the compressed data if asked */
561 if (read_flags & GIF_READ_COMPRESSED) {
562 if (!read_compressed_image(gfi, grr, read_flags))
563 return 0;
564 if (read_flags & GIF_READ_UNCOMPRESSED) {
565 Gif_Reader new_grr;
566 make_data_reader(&new_grr, gfi->compressed, gfi->compressed_len);
567 if (!uncompress_image(gfc, gfi, &new_grr))
568 return 0;
569 }
570
571 } else if (read_flags & GIF_READ_UNCOMPRESSED) {
572 if (!uncompress_image(gfc, gfi, grr))
573 return 0;
574
575 } else {
576 /* skip over the image */
577 byte buffer[GIF_MAX_BLOCK];
578 int i = gifgetbyte(grr);
579 while (i > 0) {
580 gifgetblock(buffer, i, grr);
581 i = gifgetbyte(grr);
582 }
583 }
584
585 return 1;
586 }
587
588
589 static void
read_graphic_control_extension(Gif_Context * gfc,Gif_Image * gfi,Gif_Reader * grr)590 read_graphic_control_extension(Gif_Context *gfc, Gif_Image *gfi,
591 Gif_Reader *grr)
592 {
593 byte len;
594 byte crap[GIF_MAX_BLOCK];
595
596 len = gifgetbyte(grr);
597
598 if (len == 4) {
599 byte packed = gifgetbyte(grr);
600 gfi->disposal = (packed >> 2) & 0x07;
601 gfi->delay = gifgetunsigned(grr);
602 gfi->transparent = gifgetbyte(grr);
603 if (!(packed & 0x01)) /* transparent color doesn't exist */
604 gfi->transparent = -1;
605 len -= 4;
606 }
607
608 if (len > 0) {
609 gif_read_error(gfc, "odd graphic extension format");
610 gifgetblock(crap, len, grr);
611 }
612
613 len = gifgetbyte(grr);
614 while (len > 0) {
615 gif_read_error(gfc, "odd graphic extension format");
616 gifgetblock(crap, len, grr);
617 len = gifgetbyte(grr);
618 }
619 }
620
621
622 static char *last_name;
623
624
625 static char *
suck_data(char * data,int * store_len,Gif_Reader * grr)626 suck_data(char *data, int *store_len, Gif_Reader *grr)
627 {
628 byte len = gifgetbyte(grr);
629 int total_len = 0;
630
631 while (len > 0) {
632 Gif_ReArray(data, char, total_len + len + 1);
633 if (!data) return 0;
634 gifgetblock((byte *)data, len, grr);
635
636 total_len += len;
637 data[total_len] = 0;
638
639 len = gifgetbyte(grr);
640 }
641
642 if (store_len) *store_len = total_len;
643 return data;
644 }
645
646
647 static int
read_unknown_extension(Gif_Stream * gfs,int kind,char * app_name,int position,Gif_Reader * grr)648 read_unknown_extension(Gif_Stream *gfs, int kind, char *app_name, int position,
649 Gif_Reader *grr)
650 {
651 byte block_len = gifgetbyte(grr);
652 byte *data = 0;
653 byte data_len = 0;
654 Gif_Extension *gfex = 0;
655
656 while (block_len > 0) {
657 if (data) Gif_ReArray(data, byte, data_len + block_len + 1);
658 else data = Gif_NewArray(byte, block_len + 1);
659 if (!data) goto done;
660 gifgetblock(data + data_len, block_len, grr);
661 data_len += block_len;
662 block_len = gifgetbyte(grr);
663 }
664
665 if (data)
666 gfex = Gif_NewExtension(kind, app_name);
667 if (gfex) {
668 gfex->data = data;
669 gfex->length = data_len;
670 data[data_len] = 0;
671 Gif_AddExtension(gfs, gfex, position);
672 }
673
674 done:
675 if (!gfex) Gif_DeleteArray(data);
676 while (block_len > 0) {
677 byte buffer[GIF_MAX_BLOCK];
678 gifgetblock(buffer, block_len, grr);
679 block_len = gifgetbyte(grr);
680 }
681 return gfex != 0;
682 }
683
684
685 static int
read_application_extension(Gif_Context * gfc,Gif_Image * gfi,int position,Gif_Reader * grr)686 read_application_extension(Gif_Context *gfc, Gif_Image *gfi, int position,
687 Gif_Reader *grr)
688 {
689 Gif_Stream *gfs = gfc->stream;
690 byte buffer[GIF_MAX_BLOCK + 1];
691 byte len = gifgetbyte(grr);
692 gifgetblock(buffer, len, grr);
693
694 /* Read the Netscape loop extension. */
695 if (len == 11 && memcmp(buffer, "NETSCAPE2.0", 11) == 0) {
696
697 len = gifgetbyte(grr);
698 if (len == 3) {
699 gifgetbyte(grr); /* throw away the 1 */
700 gfs->loopcount = gifgetunsigned(grr);
701 len = gifgetbyte(grr);
702 if (len) gif_read_error(gfc, "bad loop extension");
703 } else
704 gif_read_error(gfc, "bad loop extension");
705
706 while (len > 0) {
707 gifgetblock(buffer, len, grr);
708 len = gifgetbyte(grr);
709 }
710 return 1;
711
712 } else {
713 buffer[len] = 0;
714 return read_unknown_extension(gfs, 0xFF, (char *)buffer, position, grr);
715 }
716 }
717
718
719 static int
read_comment_extension(Gif_Image * gfi,Gif_Reader * grr)720 read_comment_extension(Gif_Image *gfi, Gif_Reader *grr)
721 {
722 int len;
723 Gif_Comment *gfcom = gfi->comment;
724 char *m = suck_data(0, &len, grr);
725 if (m) {
726 if (!gfcom)
727 gfcom = gfi->comment = Gif_NewComment();
728 if (!gfcom || !Gif_AddCommentTake(gfcom, m, len))
729 return 0;
730 }
731 return 1;
732 }
733
734
735 static Gif_Stream *
read_gif(Gif_Reader * grr,int read_flags,Gif_ReadErrorHandler handler,void * handler_thunk)736 read_gif(Gif_Reader *grr, int read_flags,
737 Gif_ReadErrorHandler handler, void *handler_thunk)
738 {
739 Gif_Stream *gfs;
740 Gif_Image *gfi;
741 Gif_Image *new_gfi;
742 Gif_Context gfc;
743 int extension_position = 0;
744 int unknown_block_type = 0;
745
746 if (gifgetc(grr) != 'G' ||
747 gifgetc(grr) != 'I' ||
748 gifgetc(grr) != 'F')
749 return 0;
750 (void)gifgetc(grr);
751 (void)gifgetc(grr);
752 (void)gifgetc(grr);
753
754 gfs = Gif_NewStream();
755 gfi = Gif_NewImage();
756
757 gfc.stream = gfs;
758 gfc.prefix = Gif_NewArray(Gif_Code, GIF_MAX_CODE);
759 gfc.suffix = Gif_NewArray(byte, GIF_MAX_CODE);
760 gfc.length = Gif_NewArray(u_int16_t, GIF_MAX_CODE);
761 gfc.handler = handler;
762 gfc.handler_thunk = handler_thunk;
763
764 if (!gfs || !gfi || !gfc.prefix || !gfc.suffix || !gfc.length)
765 goto done;
766
767 GIF_DEBUG(("\nGIF"));
768 if (!read_logical_screen_descriptor(gfs, grr))
769 goto done;
770 GIF_DEBUG(("logscrdesc"));
771
772 while (!gifeof(grr)) {
773
774 byte block = gifgetbyte(grr);
775
776 switch (block) {
777
778 case ',': /* image block */
779 GIF_DEBUG(("imageread %d", gfs->nimages));
780
781 gfi->identifier = last_name;
782 last_name = 0;
783 if (!read_image(grr, &gfc, gfi, read_flags)
784 || !Gif_AddImage(gfs, gfi)) {
785 Gif_DeleteImage(gfi);
786 goto done;
787 }
788
789 new_gfi = Gif_NewImage();
790 if (!new_gfi) goto done;
791
792 gfi = new_gfi;
793 extension_position++;
794 break;
795
796 case ';': /* terminator */
797 GIF_DEBUG(("term\n"));
798 goto done;
799
800 case '!': /* extension */
801 block = gifgetbyte(grr);
802 GIF_DEBUG(("ext(0x%02X)", block));
803 switch (block) {
804
805 case 0xF9:
806 read_graphic_control_extension(&gfc, gfi, grr);
807 break;
808
809 case 0xCE:
810 last_name = suck_data(last_name, 0, grr);
811 break;
812
813 case 0xFE:
814 if (!read_comment_extension(gfi, grr)) goto done;
815 break;
816
817 case 0xFF:
818 read_application_extension(&gfc, gfi, extension_position, grr);
819 break;
820
821 default:
822 read_unknown_extension(gfs, block, 0, extension_position, grr);
823 break;
824
825 }
826 break;
827
828 default:
829 if (!unknown_block_type) {
830 char buf[256];
831 sprintf(buf, "unknown block type %d at file offset %d", block, gifgetoffset(grr) - 1);
832 gif_read_error(&gfc, buf);
833 unknown_block_type = 1;
834 }
835 break;
836
837 }
838
839 }
840
841 done:
842
843 /* Move comments after last image into stream. */
844 gfs->comment = gfi->comment;
845 gfi->comment = 0;
846
847 Gif_DeleteImage(gfi);
848 Gif_DeleteArray(last_name);
849 Gif_DeleteArray(gfc.prefix);
850 Gif_DeleteArray(gfc.suffix);
851 Gif_DeleteArray(gfc.length);
852 return gfs;
853 }
854
855
856 Gif_Stream *
Gif_FullReadFile(FILE * f,int read_flags,Gif_ReadErrorHandler h,void * hthunk)857 Gif_FullReadFile(FILE *f, int read_flags,
858 Gif_ReadErrorHandler h, void *hthunk)
859 {
860 Gif_Reader grr;
861 if (!f) return 0;
862 grr.f = f;
863 grr.is_record = 0;
864 grr.byte_getter = file_byte_getter;
865 grr.block_getter = file_block_getter;
866 grr.offseter = file_offseter;
867 grr.eofer = file_eofer;
868 return read_gif(&grr, read_flags, h, hthunk);
869 }
870
871 Gif_Stream *
Gif_FullReadRecord(const Gif_Record * gifrec,int read_flags,Gif_ReadErrorHandler h,void * hthunk)872 Gif_FullReadRecord(const Gif_Record *gifrec, int read_flags,
873 Gif_ReadErrorHandler h, void *hthunk)
874 {
875 Gif_Reader grr;
876 if (!gifrec) return 0;
877 make_data_reader(&grr, gifrec->data, gifrec->length);
878 if (read_flags & GIF_READ_CONST_RECORD)
879 read_flags |= GIF_READ_COMPRESSED;
880 return read_gif(&grr, read_flags, h, hthunk);
881 }
882
883
884 #undef Gif_ReadFile
885 #undef Gif_ReadRecord
886
887 Gif_Stream *
Gif_ReadFile(FILE * f)888 Gif_ReadFile(FILE *f)
889 {
890 return Gif_FullReadFile(f, GIF_READ_UNCOMPRESSED, 0, 0);
891 }
892
893 Gif_Stream *
Gif_ReadRecord(const Gif_Record * gifrec)894 Gif_ReadRecord(const Gif_Record *gifrec)
895 {
896 return Gif_FullReadRecord(gifrec, GIF_READ_UNCOMPRESSED, 0, 0);
897 }
898
899
900 #ifdef __cplusplus
901 }
902 #endif
903