/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/gifdecod.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/gifdecod.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22