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