1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/gifdecod.cpp
3 // Purpose: wxGIFDecoder, GIF reader for wxImage and wxAnimation
4 // Author: Guillermo Rodriguez Garcia <guille@iies.es>
7 // Copyright: (c) Guillermo Rodriguez Garcia
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #if wxUSE_STREAMS && wxUSE_GIF
21 #include "wx/palette.h"
26 #include "wx/gifdecod.h"
27 #include "wx/ptr_scpd.h"
28 #include "wx/scopeguard.h"
32 //---------------------------------------------------------------------------
34 //---------------------------------------------------------------------------
36 // internal class for storing GIF image data
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
54 DECLARE_NO_COPY_CLASS(GIFImage
)
57 wxDECLARE_SCOPED_PTR(GIFImage
, GIFImagePtr
)
58 wxDEFINE_SCOPED_PTR(GIFImage
, GIFImagePtr
)
61 //---------------------------------------------------------------------------
62 // GIFImage constructor
63 //---------------------------------------------------------------------------
71 disposal
= wxANIM_DONOTREMOVE
;
73 p
= (unsigned char *) NULL
;
74 pal
= (unsigned char *) NULL
;
78 //---------------------------------------------------------------------------
79 // wxGIFDecoder constructor and destructor
80 //---------------------------------------------------------------------------
82 wxGIFDecoder::wxGIFDecoder()
86 wxGIFDecoder::~wxGIFDecoder()
91 void wxGIFDecoder::Destroy()
93 wxASSERT(m_nFrames
==m_frames
.GetCount());
94 for (unsigned int i
=0; i
<m_nFrames
; i
++)
96 GIFImage
*f
= (GIFImage
*)m_frames
[i
];
107 //---------------------------------------------------------------------------
108 // Convert this image to a wxImage object
109 //---------------------------------------------------------------------------
111 // This function was designed by Vaclav Slavik
113 bool wxGIFDecoder::ConvertToImage(unsigned int frame
, wxImage
*image
) const
115 unsigned char *src
, *dst
, *pal
;
123 wxSize sz
= GetFrameSize(frame
);
124 image
->Create(sz
.GetWidth(), sz
.GetHeight());
129 pal
= GetPalette(frame
);
130 src
= GetData(frame
);
131 dst
= image
->GetData();
132 transparent
= GetTransparentColourIndex(frame
);
134 // set transparent colour mask
135 if (transparent
!= -1)
137 for (i
= 0; i
< GetNcolours(frame
); i
++)
139 if ((pal
[3 * i
+ 0] == 255) &&
140 (pal
[3 * i
+ 1] == 0) &&
141 (pal
[3 * i
+ 2] == 255))
143 pal
[3 * i
+ 2] = 254;
147 pal
[3 * transparent
+ 0] = 255,
148 pal
[3 * transparent
+ 1] = 0,
149 pal
[3 * transparent
+ 2] = 255;
151 image
->SetMaskColour(255, 0, 255);
154 image
->SetMask(false);
157 unsigned char r
[256];
158 unsigned char g
[256];
159 unsigned char b
[256];
161 for (i
= 0; i
< 256; i
++)
168 image
->SetPalette(wxPalette(GetNcolours(frame
), r
, g
, b
));
169 #endif // wxUSE_PALETTE
172 unsigned long npixel
= sz
.GetWidth() * sz
.GetHeight();
173 for (i
= 0; i
< npixel
; i
++, src
++)
175 *(dst
++) = pal
[3 * (*src
) + 0];
176 *(dst
++) = pal
[3 * (*src
) + 1];
177 *(dst
++) = pal
[3 * (*src
) + 2];
184 //---------------------------------------------------------------------------
186 //---------------------------------------------------------------------------
188 #define GetFrame(n) ((GIFImage*)m_frames[n])
191 // Get data for current frame
193 wxSize
wxGIFDecoder::GetFrameSize(unsigned int frame
) const
195 return wxSize(GetFrame(frame
)->w
, GetFrame(frame
)->h
);
198 wxPoint
wxGIFDecoder::GetFramePosition(unsigned int frame
) const
200 return wxPoint(GetFrame(frame
)->left
, GetFrame(frame
)->top
);
203 wxAnimationDisposal
wxGIFDecoder::GetDisposalMethod(unsigned int frame
) const
205 return GetFrame(frame
)->disposal
;
208 long wxGIFDecoder::GetDelay(unsigned int frame
) const
210 return GetFrame(frame
)->delay
;
213 wxColour
wxGIFDecoder::GetTransparentColour(unsigned int frame
) const
215 unsigned char *pal
= GetFrame(frame
)->pal
;
216 int n
= GetFrame(frame
)->transparent
;
220 return wxColour(pal
[n
*3 + 0],
225 unsigned char* wxGIFDecoder::GetData(unsigned int frame
) const { return (GetFrame(frame
)->p
); }
226 unsigned char* wxGIFDecoder::GetPalette(unsigned int frame
) const { return (GetFrame(frame
)->pal
); }
227 unsigned int wxGIFDecoder::GetNcolours(unsigned int frame
) const { return (GetFrame(frame
)->ncolours
); }
228 int wxGIFDecoder::GetTransparentColourIndex(unsigned int frame
) const { return (GetFrame(frame
)->transparent
); }
232 //---------------------------------------------------------------------------
233 // GIF reading and decoding
234 //---------------------------------------------------------------------------
237 // Reads the next code from the file stream, with size 'bits'
239 int wxGIFDecoder::getcode(wxInputStream
& stream
, int bits
, int ab_fin
)
241 unsigned int mask
; // bit mask
242 unsigned int code
; // code (result)
244 // get remaining bits from last byte read
245 mask
= (1 << bits
) - 1;
246 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
248 // keep reading new bytes while needed
249 while (bits
> m_restbits
)
251 // if no bytes left in this block, read the next block
254 m_restbyte
= (unsigned char)stream
.GetC();
256 /* Some encoders are a bit broken: instead of issuing
257 * an end-of-image symbol (ab_fin) they come up with
258 * a zero-length subblock!! We catch this here so
259 * that the decoder sees an ab_fin code.
268 stream
.Read((void *) m_buffer
, m_restbyte
);
269 if (stream
.LastRead() != m_restbyte
)
277 // read next byte and isolate the bits we need
278 m_lastbyte
= (unsigned char) (*m_bufp
++);
279 mask
= (1 << (bits
- m_restbits
)) - 1;
280 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
283 // adjust total number of bits extracted from the buffer
284 m_restbits
= m_restbits
+ 8;
287 // find number of bits remaining for next code
288 m_restbits
= (m_restbits
- bits
);
295 // GIF decoding function. The initial code size (aka root size)
296 // is 'bits'. Supports interlaced images (interl == 1).
297 // Returns wxGIF_OK (== 0) on success, or an error code if something
298 // fails (see header file for details)
300 wxGIFDecoder::dgif(wxInputStream
& stream
, GIFImage
*img
, int interl
, int bits
)
302 static const int allocSize
= 4096 + 1;
303 int *ab_prefix
= new int[allocSize
]; // alphabet (prefixes)
304 if (ab_prefix
== NULL
)
309 int *ab_tail
= new int[allocSize
]; // alphabet (tails)
316 int *stack
= new int[allocSize
]; // decompression stack
324 int ab_clr
; // clear code
325 int ab_fin
; // end of info code
326 int ab_bits
; // actual symbol width, in bits
327 int ab_free
; // first free position in alphabet
328 int ab_max
; // last possible character in alphabet
329 int pass
; // pass number in interlaced images
330 int pos
; // index into decompresion stack
331 unsigned int x
, y
; // position in image buffer
333 int code
, readcode
, lastcode
, abcabca
;
335 // these won't change
336 ab_clr
= (1 << bits
);
337 ab_fin
= (1 << bits
) + 1;
339 // these will change through the decompression proccess
341 ab_free
= (1 << bits
) + 2;
342 ab_max
= (1 << ab_bits
) - 1;
348 // reset decoder vars
356 readcode
= code
= getcode(stream
, ab_bits
, ab_fin
);
359 if (code
== ab_fin
) break;
364 // reset main variables
366 ab_free
= (1 << bits
) + 2;
367 ab_max
= (1 << ab_bits
) - 1;
375 // unknown code: special case (like in ABCABCA)
378 code
= lastcode
; // take last string
379 stack
[pos
++] = abcabca
; // add first character
382 // build the string for this code in the stack
383 while (code
> ab_clr
)
385 stack
[pos
++] = ab_tail
[code
];
386 code
= ab_prefix
[code
];
388 // Don't overflow. This shouldn't happen with normal
389 // GIF files, the allocSize of 4096+1 is enough. This
390 // will only happen with badly formed GIFs.
391 if (pos
>= allocSize
)
396 return wxGIF_INVFORMAT
;
400 if (pos
>= allocSize
)
405 return wxGIF_INVFORMAT
;
408 stack
[pos
] = code
; // push last code into the stack
409 abcabca
= code
; // save for special case
411 // make new entry in alphabet (only if NOT just cleared)
414 // Normally, after the alphabet is full and can't grow any
415 // further (ab_free == 4096), encoder should (must?) emit CLEAR
416 // to reset it. This checks whether we really got it, otherwise
417 // the GIF is damaged.
418 if (ab_free
> ab_max
)
423 return wxGIF_INVFORMAT
;
426 // This assert seems unnecessary since the condition above
427 // eliminates the only case in which it went false. But I really
428 // don't like being forced to ask "Who in .text could have
429 // written there?!" And I wouldn't have been forced to ask if
430 // this line had already been here.
431 wxASSERT(ab_free
< allocSize
);
433 ab_prefix
[ab_free
] = lastcode
;
434 ab_tail
[ab_free
] = code
;
437 if ((ab_free
> ab_max
) && (ab_bits
< 12))
440 ab_max
= (1 << ab_bits
) - 1;
444 // dump stack data to the image buffer
447 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
456 // support for interlaced images
459 case 1: y
+= 8; break;
460 case 2: y
+= 8; break;
461 case 3: y
+= 4; break;
462 case 4: y
+= 2; break;
465 /* loop until a valid y coordinate has been
466 found, Or if the maximum number of passes has
467 been reached, exit the loop, and stop image
468 decoding (At this point the image is successfully
470 If we don't loop, but merely set y to some other
471 value, that new value might still be invalid depending
472 on the height of the image. This would cause out of
475 while (y
>= (img
->h
))
479 case 2: y
= 4; break;
480 case 3: y
= 2; break;
481 case 4: y
= 1; break;
485 It's possible we arrive here. For example this
486 happens when the image is interlaced, and the
487 height is 1. Looking at the above cases, the
488 lowest possible y is 1. While the only valid
489 one would be 0 for an image of height 1. So
490 'eventually' the loop will arrive here.
491 This case makes sure this while loop is
492 exited, as well as the 2 other ones.
495 // Set y to a valid coordinate so the local
496 // while loop will be exited. (y = 0 always
497 // is >= img->h since if img->h == 0 the
498 // image is never decoded)
501 // This will exit the other outer while loop
504 // This will halt image decoding.
516 Normally image decoding is finished when an End of Information code is
517 encountered (code == ab_fin) however some broken encoders write wrong
518 "block byte counts" (The first byte value after the "code size" byte),
519 being one value too high. It might very well be possible other variants
520 of this problem occur as well. The only sensible solution seems to
521 be to check for clipping.
522 Example of wrong encoding:
523 (1 * 1 B/W image, raster data stream follows in hex bytes)
525 02 << B/W images have a code size of 2
526 02 << Block byte count
528 00 << Zero byte count (terminates data stream)
530 Because the block byte count is 2, the zero byte count is used in the
531 decoding process, and decoding is continued after this byte. (While it
532 should signal an end of image)
538 01 << When decoded this correctly includes the End of Information code
546 (The 44 doesn't include an End of Information code, but at least the
547 decoder correctly skips to 00 now after decoding, and signals this
548 as an End of Information itself)
562 while (code
!= ab_fin
);
564 delete [] ab_prefix
;
573 // Returns true if the file looks like a valid GIF, false otherwise.
575 bool wxGIFDecoder::CanRead(wxInputStream
&stream
) const
577 unsigned char buf
[3];
579 if ( !stream
.Read(buf
, WXSIZEOF(buf
)) )
582 stream
.SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
);
584 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
589 // Reads and decodes one or more GIF images, depending on whether
590 // animated GIF support is enabled. Can read GIFs with any bit
591 // size (color depth), but the output images are always expanded
592 // to 8 bits per pixel. Also, the image palettes always contain
593 // 256 colors, although some of them may be unused. Returns wxGIF_OK
594 // (== 0) on success, or an error code if something fails (see
595 // header file for details)
597 wxGIFErrorCode
wxGIFDecoder::LoadGIF(wxInputStream
& stream
)
599 unsigned int global_ncolors
= 0;
600 int bits
, interl
, transparent
, i
;
601 wxAnimationDisposal disposal
;
604 unsigned char type
= 0;
605 unsigned char pal
[768];
606 unsigned char buf
[16];
609 // check GIF signature
610 if (!CanRead(stream
))
611 return wxGIF_INVFORMAT
;
613 // check for animated GIF support (ver. >= 89a)
615 static const unsigned int headerSize
= (3 + 3);
616 stream
.Read(buf
, headerSize
);
617 if (stream
.LastRead() != headerSize
)
619 return wxGIF_INVFORMAT
;
622 if (memcmp(buf
+ 3, "89a", 3) < 0)
627 // read logical screen descriptor block (LSDB)
628 static const unsigned int lsdbSize
= (2 + 2 + 1 + 1 + 1);
629 stream
.Read(buf
, lsdbSize
);
630 if (stream
.LastRead() != lsdbSize
)
632 return wxGIF_INVFORMAT
;
635 m_szAnimation
.SetWidth( buf
[0] + 256 * buf
[1] );
636 m_szAnimation
.SetHeight( buf
[2] + 256 * buf
[3] );
638 if (anim
&& ((m_szAnimation
.GetWidth() == 0) || (m_szAnimation
.GetHeight() == 0)))
640 return wxGIF_INVFORMAT
;
643 // load global color map if available
644 if ((buf
[4] & 0x80) == 0x80)
646 int backgroundColIndex
= buf
[5];
648 global_ncolors
= 2 << (buf
[4] & 0x07);
649 unsigned int numBytes
= 3 * global_ncolors
;
650 stream
.Read(pal
, numBytes
);
651 if (stream
.LastRead() != numBytes
)
653 return wxGIF_INVFORMAT
;
656 m_background
.Set(pal
[backgroundColIndex
*3 + 0],
657 pal
[backgroundColIndex
*3 + 1],
658 pal
[backgroundColIndex
*3 + 2]);
661 // transparent colour, disposal method and delay default to unused
663 disposal
= wxANIM_UNSPECIFIED
;
669 type
= (unsigned char)stream
.GetC();
672 If the end of file has been reached (or an error) and a ";"
673 (0x3B) hasn't been encountered yet, exit the loop. (Without this
674 check the while loop would loop endlessly.) Later on, in the next while
675 loop, the file will be treated as being truncated (But still
676 be decoded as far as possible). returning wxGIF_TRUNCATED is not
677 possible here since some init code is done after this loop.
679 if (stream
.Eof())// || !stream.IsOk())
682 type is set to some bogus value, so there's no
683 need to continue evaluating it.
685 break; // Alternative : "return wxGIF_INVFORMAT;"
697 if (((unsigned char)stream
.GetC()) == 0xF9)
698 // graphics control extension, parse it
700 static const unsigned int gceSize
= 6;
701 stream
.Read(buf
, gceSize
);
702 if (stream
.LastRead() != gceSize
)
705 return wxGIF_INVFORMAT
;
708 // read delay and convert from 1/100 of a second to ms
709 delay
= 10 * (buf
[2] + 256 * buf
[3]);
711 // read transparent colour index, if used
713 transparent
= buf
[4];
715 // read disposal method
716 disposal
= (wxAnimationDisposal
)(((buf
[1] & 0x1C) >> 2) - 1);
719 // other extension, skip
721 while ((i
= (unsigned char)stream
.GetC()) != 0)
723 if (stream
.Eof() || (stream
.LastRead() == 0))
728 stream
.SeekI(i
, wxFromCurrent
);
733 // image descriptor block?
736 // allocate memory for IMAGEN struct
737 GIFImagePtr
pimg(new GIFImage());
739 wxScopeGuard guardDestroy
= wxMakeObjGuard(*this, &wxGIFDecoder::Destroy
);
745 static const unsigned int idbSize
= (2 + 2 + 2 + 2 + 1);
746 stream
.Read(buf
, idbSize
);
747 if (stream
.LastRead() != idbSize
)
748 return wxGIF_INVFORMAT
;
750 pimg
->left
= buf
[0] + 256 * buf
[1];
751 pimg
->top
= buf
[2] + 256 * buf
[3];
753 pimg->left = buf[4] + 256 * buf[5];
754 pimg->top = buf[4] + 256 * buf[5];
756 pimg
->w
= buf
[4] + 256 * buf
[5];
757 pimg
->h
= buf
[6] + 256 * buf
[7];
759 if ( anim
&& ((pimg
->w
== 0) || (pimg
->w
> (unsigned int)m_szAnimation
.GetWidth()) ||
760 (pimg
->h
== 0) || (pimg
->h
> (unsigned int)m_szAnimation
.GetHeight())) )
761 return wxGIF_INVFORMAT
;
763 interl
= ((buf
[8] & 0x40)? 1 : 0);
764 size
= pimg
->w
* pimg
->h
;
766 pimg
->transparent
= transparent
;
767 pimg
->disposal
= disposal
;
770 // allocate memory for image and palette
771 pimg
->p
= (unsigned char *) malloc((unsigned int)size
);
772 pimg
->pal
= (unsigned char *) malloc(768);
774 if ((!pimg
->p
) || (!pimg
->pal
))
777 // load local color map if available, else use global map
778 if ((buf
[8] & 0x80) == 0x80)
780 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
781 unsigned int numBytes
= 3 * local_ncolors
;
782 stream
.Read(pimg
->pal
, numBytes
);
783 pimg
->ncolours
= local_ncolors
;
784 if (stream
.LastRead() != numBytes
)
785 return wxGIF_INVFORMAT
;
789 memcpy(pimg
->pal
, pal
, 768);
790 pimg
->ncolours
= global_ncolors
;
793 // get initial code size from first byte in raster data
794 bits
= (unsigned char)stream
.GetC();
796 return wxGIF_INVFORMAT
;
799 wxGIFErrorCode result
= dgif(stream
, pimg
.get(), interl
, bits
);
800 if (result
!= wxGIF_OK
)
803 guardDestroy
.Dismiss();
805 // add the image to our frame array
806 m_frames
.Add(pimg
.release());
809 // if this is not an animated GIF, exit after first image
818 return wxGIF_INVFORMAT
;
821 // try to read to the end of the stream
825 return wxGIF_TRUNCATED
;
827 type
= (unsigned char)stream
.GetC();
832 (void) stream
.GetC();
835 while ((i
= (unsigned char)stream
.GetC()) != 0)
837 if (stream
.Eof() || (stream
.LastRead() == 0))
840 return wxGIF_INVFORMAT
;
842 stream
.SeekI(i
, wxFromCurrent
);
845 else if (type
== 0x2C)
847 // image descriptor block
848 static const unsigned int idbSize
= (2 + 2 + 2 + 2 + 1);
849 stream
.Read(buf
, idbSize
);
850 if (stream
.LastRead() != idbSize
)
853 return wxGIF_INVFORMAT
;
857 if ((buf
[8] & 0x80) == 0x80)
859 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
860 wxFileOffset numBytes
= 3 * local_ncolors
;
861 stream
.SeekI(numBytes
, wxFromCurrent
);
865 (void) stream
.GetC();
866 if (stream
.Eof() || (stream
.LastRead() == 0))
869 return wxGIF_INVFORMAT
;
873 while ((i
= (unsigned char)stream
.GetC()) != 0)
875 if (stream
.Eof() || (stream
.LastRead() == 0))
878 return wxGIF_INVFORMAT
;
880 stream
.SeekI(i
, wxFromCurrent
);
883 else if ((type
!= 0x3B) && (type
!= 00)) // testing
885 // images are OK, but couldn't read to the end of the stream
886 return wxGIF_TRUNCATED
;
893 #endif // wxUSE_STREAMS && wxUSE_GIF