]> git.saurik.com Git - wxWidgets.git/blob - src/common/gifdecod.cpp
8213e583ef1dbeccd8285b2b322004d547ff49d5
[wxWidgets.git] / src / common / gifdecod.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gifdecod.cpp
3 // Purpose: wxGIFDecoder, GIF reader for wxImage and wxAnimation
4 // Author: Guillermo Rodriguez Garcia <guille@iies.es>
5 // Version: 3.04
6 // RCS-ID: $Id$
7 // Copyright: (c) Guillermo Rodriguez Garcia
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 # pragma hdrstop
16 #endif
17
18 #ifndef WX_PRECOMP
19 # include "wx/defs.h"
20 # include "wx/palette.h"
21 #endif
22
23 #if wxUSE_STREAMS && wxUSE_GIF
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include "wx/gifdecod.h"
28
29
30 //---------------------------------------------------------------------------
31 // GIFImage constructor
32 //---------------------------------------------------------------------------
33 GIFImage::GIFImage()
34 {
35 w = 0;
36 h = 0;
37 left = 0;
38 top = 0;
39 transparent = 0;
40 disposal = 0;
41 delay = -1;
42 p = (unsigned char *) NULL;
43 pal = (unsigned char *) NULL;
44 next = (GIFImage *) NULL;
45 prev = (GIFImage *) NULL;
46 }
47
48 //---------------------------------------------------------------------------
49 // wxGIFDecoder constructor and destructor
50 //---------------------------------------------------------------------------
51
52 wxGIFDecoder::wxGIFDecoder(wxInputStream *s, bool anim)
53 {
54 m_f = s;
55 m_anim = anim;
56
57 m_background = -1;
58 m_screenw = 0;
59 m_screenh = 0;
60
61 m_pimage = NULL;
62 m_pfirst = NULL;
63 m_plast = NULL;
64 m_image = 0;
65 m_nimages = 0;
66 }
67
68 wxGIFDecoder::~wxGIFDecoder()
69 {
70 Destroy();
71 }
72
73 void wxGIFDecoder::Destroy()
74 {
75 GIFImage *pimg, *paux;
76
77 pimg = m_pfirst;
78
79 while (pimg != NULL)
80 {
81 paux = pimg->next;
82 free(pimg->p);
83 free(pimg->pal);
84 delete pimg;
85 pimg = paux;
86 }
87
88 m_pimage = NULL;
89 m_pfirst = NULL;
90 m_plast = NULL;
91 m_image = 0;
92 m_nimages = 0;
93 }
94
95
96 //---------------------------------------------------------------------------
97 // Convert this image to a wxImage object
98 //---------------------------------------------------------------------------
99
100 // This function was designed by Vaclav Slavik
101
102 bool wxGIFDecoder::ConvertToImage(wxImage *image) const
103 {
104 unsigned char *src, *dst, *pal;
105 unsigned long i;
106 int transparent;
107
108 /* just in case... */
109 image->Destroy();
110
111 /* create the image */
112 image->Create(GetWidth(), GetHeight());
113
114 if (!image->Ok())
115 return false;
116
117 pal = GetPalette();
118 src = GetData();
119 dst = image->GetData();
120 transparent = GetTransparentColour();
121
122 /* set transparent colour mask */
123 if (transparent != -1)
124 {
125 for (i = 0; i < 256; i++)
126 {
127 if ((pal[3 * i + 0] == 255) &&
128 (pal[3 * i + 1] == 0) &&
129 (pal[3 * i + 2] == 255))
130 {
131 pal[3 * i + 2] = 254;
132 }
133 }
134
135 pal[3 * transparent + 0] = 255,
136 pal[3 * transparent + 1] = 0,
137 pal[3 * transparent + 2] = 255;
138
139 image->SetMaskColour(255, 0, 255);
140 }
141 else
142 image->SetMask(false);
143
144 #if wxUSE_PALETTE
145 if (pal)
146 {
147 unsigned char r[256];
148 unsigned char g[256];
149 unsigned char b[256];
150
151 for (i = 0; i < 256; i++)
152 {
153 r[i] = pal[3*i + 0];
154 g[i] = pal[3*i + 1];
155 b[i] = pal[3*i + 2];
156 }
157
158 image->SetPalette(wxPalette(256, r, g, b));
159 }
160 #endif // wxUSE_PALETTE
161
162 /* copy image data */
163 for (i = 0; i < (GetWidth() * GetHeight()); i++, src++)
164 {
165 *(dst++) = pal[3 * (*src) + 0];
166 *(dst++) = pal[3 * (*src) + 1];
167 *(dst++) = pal[3 * (*src) + 2];
168 }
169
170 return true;
171 }
172
173
174 //---------------------------------------------------------------------------
175 // Data accessors
176 //---------------------------------------------------------------------------
177
178 // Get data for current frame
179
180 int wxGIFDecoder::GetFrameIndex() const { return m_image; }
181 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage->p); }
182 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage->pal); }
183 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage->w); }
184 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage->h); }
185 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage->top); }
186 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage->left); }
187 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage->transparent); }
188 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage->disposal); }
189 long wxGIFDecoder::GetDelay() const { return (m_pimage->delay); }
190
191 // Get global data
192
193 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw; }
194 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh; }
195 int wxGIFDecoder::GetBackgroundColour() const { return m_background; }
196 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages; }
197 bool wxGIFDecoder::IsAnimation() const { return (m_nimages > 1); }
198
199
200 //---------------------------------------------------------------------------
201 // Functions to move through the animation
202 //---------------------------------------------------------------------------
203
204 bool wxGIFDecoder::GoFirstFrame()
205 {
206 if (!IsAnimation())
207 return false;
208
209 m_image = 1;
210 m_pimage = m_pfirst;
211 return true;
212 }
213
214 bool wxGIFDecoder::GoLastFrame()
215 {
216 if (!IsAnimation())
217 return false;
218
219 m_image = m_nimages;
220 m_pimage = m_plast;
221 return true;
222 }
223
224 bool wxGIFDecoder::GoNextFrame(bool cyclic)
225 {
226 if (!IsAnimation())
227 return false;
228
229 if ((m_image < m_nimages) || (cyclic))
230 {
231 m_pimage = m_pimage->next;
232 m_image++;
233
234 if (!m_pimage)
235 {
236 m_image = 1;
237 m_pimage = m_pfirst;
238 }
239
240 return true;
241 }
242 else
243 return false;
244 }
245
246 bool wxGIFDecoder::GoPrevFrame(bool cyclic)
247 {
248 if (!IsAnimation())
249 return false;
250
251 if ((m_image > 1) || (cyclic))
252 {
253 m_pimage = m_pimage->prev;
254 m_image--;
255
256 if (!m_pimage)
257 {
258 m_image = m_nimages;
259 m_pimage = m_plast;
260 }
261
262 return true;
263 }
264 else
265 return false;
266 }
267
268 bool wxGIFDecoder::GoFrame(int which)
269 {
270 if (!IsAnimation())
271 return false;
272
273 if ((which >= 1) && (which <= m_nimages))
274 {
275 m_image = 1;
276 m_pimage = m_pfirst;
277
278 while (m_image < which)
279 {
280 m_image++;
281 m_pimage = m_pimage->next;
282 }
283
284 return true;
285 }
286 else
287 return false;
288 }
289
290
291 //---------------------------------------------------------------------------
292 // GIF reading and decoding
293 //---------------------------------------------------------------------------
294
295 // getcode:
296 // Reads the next code from the file stream, with size 'bits'
297 //
298 int wxGIFDecoder::getcode(int bits, int ab_fin)
299 {
300 unsigned int mask; /* bit mask */
301 unsigned int code; /* code (result) */
302
303
304 /* get remaining bits from last byte read */
305 mask = (1 << bits) - 1;
306 code = (m_lastbyte >> (8 - m_restbits)) & mask;
307
308 /* keep reading new bytes while needed */
309 while (bits > m_restbits)
310 {
311 /* if no bytes left in this block, read the next block */
312 if (m_restbyte == 0)
313 {
314 m_restbyte = (unsigned char)m_f->GetC();
315
316 /* Some encoders are a bit broken: instead of issuing
317 * an end-of-image symbol (ab_fin) they come up with
318 * a zero-length subblock!! We catch this here so
319 * that the decoder sees an ab_fin code.
320 */
321 if (m_restbyte == 0)
322 {
323 code = ab_fin;
324 break;
325 }
326
327 /* prefetch data */
328 m_f->Read((void *) m_buffer, m_restbyte);
329 if (m_f->LastRead() != m_restbyte)
330 {
331 code = ab_fin;
332 return code;
333 }
334 m_bufp = m_buffer;
335 }
336
337 /* read next byte and isolate the bits we need */
338 m_lastbyte = (unsigned char) (*m_bufp++);
339 mask = (1 << (bits - m_restbits)) - 1;
340 code = code + ((m_lastbyte & mask) << m_restbits);
341 m_restbyte--;
342
343 /* adjust total number of bits extracted from the buffer */
344 m_restbits = m_restbits + 8;
345 }
346
347 /* find number of bits remaining for next code */
348 m_restbits = (m_restbits - bits);
349
350 return code;
351 }
352
353
354 // dgif:
355 // GIF decoding function. The initial code size (aka root size)
356 // is 'bits'. Supports interlaced images (interl == 1).
357 // Returns wxGIF_OK (== 0) on success, or an error code if something
358 // fails (see header file for details)
359 int wxGIFDecoder::dgif(GIFImage *img, int interl, int bits)
360 {
361 static const int allocSize = 4096 + 1;
362 int *ab_prefix = new int[allocSize]; /* alphabet (prefixes) */
363 if (ab_prefix == NULL)
364 {
365 return wxGIF_MEMERR;
366 }
367
368 int *ab_tail = new int[allocSize]; /* alphabet (tails) */
369 if (ab_tail == NULL)
370 {
371 delete[] ab_prefix;
372 return wxGIF_MEMERR;
373 }
374
375 int *stack = new int[allocSize]; /* decompression stack */
376 if (stack == NULL)
377 {
378 delete[] ab_prefix;
379 delete[] ab_tail;
380 return wxGIF_MEMERR;
381 }
382
383 int ab_clr; /* clear code */
384 int ab_fin; /* end of info code */
385 int ab_bits; /* actual symbol width, in bits */
386 int ab_free; /* first free position in alphabet */
387 int ab_max; /* last possible character in alphabet */
388 int pass; /* pass number in interlaced images */
389 int pos; /* index into decompresion stack */
390 unsigned int x, y; /* position in image buffer */
391
392 int code, readcode, lastcode, abcabca;
393
394 /* these won't change */
395 ab_clr = (1 << bits);
396 ab_fin = (1 << bits) + 1;
397
398 /* these will change through the decompression proccess */
399 ab_bits = bits + 1;
400 ab_free = (1 << bits) + 2;
401 ab_max = (1 << ab_bits) - 1;
402 lastcode = -1;
403 abcabca = -1;
404 pass = 1;
405 pos = x = y = 0;
406
407 /* reset decoder vars */
408 m_restbits = 0;
409 m_restbyte = 0;
410 m_lastbyte = 0;
411
412 do
413 {
414 /* get next code */
415 readcode = code = getcode(ab_bits, ab_fin);
416
417 /* end of image? */
418 if (code == ab_fin) break;
419
420 /* reset alphabet? */
421 if (code == ab_clr)
422 {
423 /* reset main variables */
424 ab_bits = bits + 1;
425 ab_free = (1 << bits) + 2;
426 ab_max = (1 << ab_bits) - 1;
427 lastcode = -1;
428 abcabca = -1;
429
430 /* skip to next code */
431 continue;
432 }
433
434 /* unknown code: special case (like in ABCABCA) */
435 if (code >= ab_free)
436 {
437 code = lastcode; /* take last string */
438 stack[pos++] = abcabca; /* add first character */
439 }
440
441 /* build the string for this code in the stack */
442 while (code > ab_clr)
443 {
444 stack[pos++] = ab_tail[code];
445 code = ab_prefix[code];
446
447 // Don't overflow. This shouldn't happen with normal
448 // GIF files, the allocSize of 4096+1 is enough. This
449 // will only happen with badly formed GIFs.
450 if (pos >= allocSize)
451 {
452 delete[] ab_prefix;
453 delete[] ab_tail;
454 delete[] stack;
455 return wxGIF_INVFORMAT;
456 }
457 }
458
459 if (pos >= allocSize)
460 {
461 delete[] ab_prefix;
462 delete[] ab_tail;
463 delete[] stack;
464 return wxGIF_INVFORMAT;
465 }
466
467 stack[pos] = code; /* push last code into the stack */
468 abcabca = code; /* save for special case */
469
470 /* make new entry in alphabet (only if NOT just cleared) */
471 if (lastcode != -1)
472 {
473 ab_prefix[ab_free] = lastcode;
474 ab_tail[ab_free] = code;
475 ab_free++;
476
477 if ((ab_free > ab_max) && (ab_bits < 12))
478 {
479 ab_bits++;
480 ab_max = (1 << ab_bits) - 1;
481 }
482 }
483
484 /* dump stack data to the image buffer */
485 while (pos >= 0)
486 {
487 (img->p)[x + (y * (img->w))] = (char) stack[pos];
488 pos--;
489
490 if (++x >= (img->w))
491 {
492 x = 0;
493
494 if (interl)
495 {
496 /* support for interlaced images */
497 switch (pass)
498 {
499 case 1: y += 8; break;
500 case 2: y += 8; break;
501 case 3: y += 4; break;
502 case 4: y += 2; break;
503 }
504
505 /* loop until a valid y coordinate has been
506 found, Or if the maximum number of passes has
507 been reached, exit the loop, and stop image
508 decoding (At this point the image is successfully
509 decoded).
510 If we don't loop, but merely set y to some other
511 value, that new value might still be invalid depending
512 on the height of the image. This would cause out of
513 bounds writing.
514 */
515 while (y >= (img->h))
516 {
517 switch (++pass)
518 {
519 case 2: y = 4; break;
520 case 3: y = 2; break;
521 case 4: y = 1; break;
522
523 default:
524 /*
525 It's possible we arrive here. For example this
526 happens when the image is interlaced, and the
527 height is 1. Looking at the above cases, the
528 lowest possible y is 1. While the only valid
529 one would be 0 for an image of height 1. So
530 'eventually' the loop will arrive here.
531 This case makes sure this while loop is
532 exited, as well as the 2 other ones.
533 */
534
535 // Set y to a valid coordinate so the local
536 // while loop will be exited. (y = 0 always
537 // is >= img->h since if img->h == 0 the
538 // image is never decoded)
539 y = 0;
540
541 // This will exit the other outer while loop
542 pos = -1;
543
544 // This will halt image decoding.
545 code = ab_fin;
546
547 break;
548 }
549 }
550 }
551 else
552 {
553 /* non-interlaced */
554 y++;
555 /*
556 Normally image decoding is finished when an End of Information code is
557 encountered (code == ab_fin) however some broken encoders write wrong
558 "block byte counts" (The first byte value after the "code size" byte),
559 being one value too high. It might very well be possible other variants
560 of this problem occur as well. The only sensible solution seems to
561 be to check for clipping.
562 Example of wrong encoding:
563 (1 * 1 B/W image, raster data stream follows in hex bytes)
564
565 02 << B/W images have a code size of 2
566 02 << Block byte count
567 44 << LZW packed
568 00 << Zero byte count (terminates data stream)
569
570 Because the block byte count is 2, the zero byte count is used in the
571 decoding process, and decoding is continued after this byte. (While it
572 should signal an end of image)
573
574 It should be:
575 02
576 02
577 44
578 01 << When decoded this correctly includes the End of Information code
579 00
580
581 Or (Worse solution):
582 02
583 01
584 44
585 00
586 (The 44 doesn't include an End of Information code, but at least the
587 decoder correctly skips to 00 now after decoding, and signals this
588 as an End of Information itself)
589 */
590 if (y >= img->h)
591 {
592 code = ab_fin;
593 break;
594 }
595 }
596 }
597 }
598
599 pos = 0;
600 lastcode = readcode;
601 }
602 while (code != ab_fin);
603
604 delete [] ab_prefix ;
605 delete [] ab_tail ;
606 delete [] stack ;
607
608 return wxGIF_OK;
609 }
610
611
612 // CanRead:
613 // Returns true if the file looks like a valid GIF, false otherwise.
614 //
615 bool wxGIFDecoder::CanRead()
616 {
617 unsigned char buf[3];
618
619 if ( !m_f->Read(buf, WXSIZEOF(buf)) )
620 return false;
621
622 m_f->SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent);
623
624 return memcmp(buf, "GIF", WXSIZEOF(buf)) == 0;
625 }
626
627
628 // ReadGIF:
629 // Reads and decodes one or more GIF images, depending on whether
630 // animated GIF support is enabled. Can read GIFs with any bit
631 // size (color depth), but the output images are always expanded
632 // to 8 bits per pixel. Also, the image palettes always contain
633 // 256 colors, although some of them may be unused. Returns wxGIF_OK
634 // (== 0) on success, or an error code if something fails (see
635 // header file for details)
636 //
637 int wxGIFDecoder::ReadGIF()
638 {
639 unsigned int ncolors;
640 int bits, interl, transparent, disposal, i;
641 long size;
642 long delay;
643 unsigned char type = 0;
644 unsigned char pal[768];
645 unsigned char buf[16];
646 GIFImage **ppimg;
647 GIFImage *pimg, *pprev;
648
649 /* check GIF signature */
650 if (!CanRead())
651 return wxGIF_INVFORMAT;
652
653 /* check for animated GIF support (ver. >= 89a) */
654
655 static const size_t headerSize = (3 + 3);
656 m_f->Read(buf, headerSize);
657 if (m_f->LastRead() != headerSize)
658 {
659 return wxGIF_INVFORMAT;
660 }
661
662 if (memcmp(buf + 3, "89a", 3) < 0)
663 {
664 m_anim = false;
665 }
666
667 /* read logical screen descriptor block (LSDB) */
668 static const size_t lsdbSize = (2 + 2 + 1 + 1 + 1);
669 m_f->Read(buf, lsdbSize);
670 if (m_f->LastRead() != lsdbSize)
671 {
672 return wxGIF_INVFORMAT;
673 }
674
675 m_screenw = buf[0] + 256 * buf[1];
676 m_screenh = buf[2] + 256 * buf[3];
677
678 const int maxScreenSize = 4 << 10;
679 if ((m_screenw <= 0) || (m_screenw > maxScreenSize) || (m_screenh <= 0) || (m_screenh > maxScreenSize))
680 {
681 return wxGIF_INVFORMAT;
682 }
683
684 /* load global color map if available */
685 if ((buf[4] & 0x80) == 0x80)
686 {
687 m_background = buf[5];
688
689 ncolors = 2 << (buf[4] & 0x07);
690 size_t numBytes = 3 * ncolors;
691 m_f->Read(pal, numBytes);
692 if (m_f->LastRead() != numBytes)
693 {
694 return wxGIF_INVFORMAT;
695 }
696 }
697
698 /* transparent colour, disposal method and delay default to unused */
699 transparent = -1;
700 disposal = -1;
701 delay = -1;
702
703 /* read images */
704 ppimg = &m_pfirst;
705 pprev = NULL;
706 pimg = NULL;
707
708 bool done = false;
709
710 while (!done)
711 {
712 type = (unsigned char)m_f->GetC();
713
714 /*
715 If the end of file has been reached (or an error) and a ";"
716 (0x3B) hasn't been encountered yet, exit the loop. (Without this
717 check the while loop would loop endlessly.) Later on, in the next while
718 loop, the file will be treated as being truncated (But still
719 be decoded as far as possible). returning wxGIF_TRUNCATED is not
720 possible here since some init code is done after this loop.
721 */
722 if (m_f->Eof())// || !m_f->IsOk())
723 {
724 /*
725 type is set to some bogus value, so there's no
726 need to continue evaluating it.
727 */
728 break; // Alternative : "return wxGIF_INVFORMAT;"
729 }
730
731 /* end of data? */
732 if (type == 0x3B)
733 {
734 done = true;
735 }
736 else
737 /* extension block? */
738 if (type == 0x21)
739 {
740 if (((unsigned char)m_f->GetC()) == 0xF9)
741 /* graphics control extension, parse it */
742 {
743 static const size_t gceSize = 6;
744 m_f->Read(buf, gceSize);
745 if (m_f->LastRead() != gceSize)
746 {
747 Destroy();
748 return wxGIF_INVFORMAT;
749 }
750
751 /* read delay and convert from 1/100 of a second to ms */
752 delay = 10 * (buf[2] + 256 * buf[3]);
753
754 /* read transparent colour index, if used */
755 if (buf[1] & 0x01)
756 transparent = buf[4];
757
758 /* read disposal method */
759 disposal = ((buf[1] & 0x1C) >> 2) - 1;
760 }
761 else
762 /* other extension, skip */
763 {
764 while ((i = (unsigned char)m_f->GetC()) != 0)
765 {
766 m_f->SeekI(i, wxFromCurrent);
767 if (m_f->Eof())
768 {
769 done = true;
770 break;
771 }
772 }
773 }
774 }
775 else
776 /* image descriptor block? */
777 if (type == 0x2C)
778 {
779 /* allocate memory for IMAGEN struct */
780 pimg = (*ppimg) = new GIFImage();
781
782 if (pimg == NULL)
783 {
784 Destroy();
785 return wxGIF_MEMERR;
786 }
787
788 /* fill in the data */
789 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
790 m_f->Read(buf, idbSize);
791 if (m_f->LastRead() != idbSize)
792 {
793 Destroy();
794 return wxGIF_INVFORMAT;
795 }
796
797 pimg->left = buf[0] + 256 * buf[1];
798 pimg->top = buf[2] + 256 * buf[3];
799 /*
800 pimg->left = buf[4] + 256 * buf[5];
801 pimg->top = buf[4] + 256 * buf[5];
802 */
803 pimg->w = buf[4] + 256 * buf[5];
804 pimg->h = buf[6] + 256 * buf[7];
805
806 if (pimg->w == 0 || pimg->h == 0)
807 {
808 Destroy();
809 return wxGIF_INVFORMAT;
810 }
811
812 interl = ((buf[8] & 0x40)? 1 : 0);
813 size = pimg->w * pimg->h;
814
815 pimg->transparent = transparent;
816 pimg->disposal = disposal;
817 pimg->delay = delay;
818 pimg->next = NULL;
819 pimg->prev = pprev;
820 pprev = pimg;
821 ppimg = &pimg->next;
822
823 /* allocate memory for image and palette */
824 pimg->p = (unsigned char *) malloc((size_t)size);
825 pimg->pal = (unsigned char *) malloc(768);
826
827 if ((!pimg->p) || (!pimg->pal))
828 {
829 Destroy();
830 return wxGIF_MEMERR;
831 }
832
833 /* load local color map if available, else use global map */
834 if ((buf[8] & 0x80) == 0x80)
835 {
836 ncolors = 2 << (buf[8] & 0x07);
837 size_t numBytes = 3 * ncolors;
838 m_f->Read(pimg->pal, numBytes);
839 if (m_f->LastRead() != numBytes)
840 {
841 Destroy();
842 return wxGIF_INVFORMAT;
843 }
844 }
845 else
846 {
847 memcpy(pimg->pal, pal, 768);
848 }
849
850 /* get initial code size from first byte in raster data */
851 bits = (unsigned char)m_f->GetC();
852 if (bits == 0)
853 {
854 Destroy();
855 return wxGIF_INVFORMAT;
856 }
857
858 /* decode image */
859 int result = dgif(pimg, interl, bits);
860 if (result != wxGIF_OK)
861 {
862 Destroy();
863 return result;
864 }
865 m_nimages++;
866
867 /* if this is not an animated GIF, exit after first image */
868 if (!m_anim)
869 done = true;
870 }
871 }
872
873 if (m_nimages <= 0)
874 {
875 Destroy();
876 return wxGIF_INVFORMAT;
877 }
878
879 /* setup image pointers */
880 m_image = 1;
881 m_plast = pimg;
882 m_pimage = m_pfirst;
883
884 /* try to read to the end of the stream */
885 while (type != 0x3B)
886 {
887 if (!m_f->IsOk())
888 return wxGIF_TRUNCATED;
889
890 type = (unsigned char)m_f->GetC();
891
892 if (type == 0x21)
893 {
894 /* extension type */
895 (void) m_f->GetC();
896
897 /* skip all data */
898 while ((i = (unsigned char)m_f->GetC()) != 0)
899 {
900 m_f->SeekI(i, wxFromCurrent);
901 }
902 }
903 else if (type == 0x2C)
904 {
905 /* image descriptor block */
906 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
907 m_f->Read(buf, idbSize);
908 if (m_f->LastRead() != idbSize)
909 {
910 Destroy();
911 return wxGIF_INVFORMAT;
912 }
913
914 /* local color map */
915 if ((buf[8] & 0x80) == 0x80)
916 {
917 ncolors = 2 << (buf[8] & 0x07);
918 if (ncolors <= 0)
919 {
920 Destroy();
921 return wxGIF_INVFORMAT;
922 }
923
924 wxFileOffset pos = m_f->TellI();
925 wxFileOffset numBytes = 3 * ncolors;
926 m_f->SeekI(numBytes, wxFromCurrent);
927 if (m_f->TellI() != (pos + numBytes))
928 {
929 Destroy();
930 return wxGIF_INVFORMAT;
931 }
932 }
933
934 /* initial code size */
935 (void) m_f->GetC();
936
937 /* skip all data */
938 while ((i = (unsigned char)m_f->GetC()) != 0)
939 {
940 m_f->SeekI(i, wxFromCurrent);
941 }
942 }
943 else if ((type != 0x3B) && (type != 00)) /* testing */
944 {
945 /* images are OK, but couldn't read to the end of the stream */
946 return wxGIF_TRUNCATED;
947 }
948 }
949
950 return wxGIF_OK;
951 }
952
953 #endif // wxUSE_STREAMS && wxUSE_GIF