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