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