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());
125 image
->SetType(wxBITMAP_TYPE_GIF
);
130 pal
= GetPalette(frame
);
131 src
= GetData(frame
);
132 dst
= image
->GetData();
133 transparent
= GetTransparentColourIndex(frame
);
135 // set transparent colour mask
136 if (transparent
!= -1)
138 for (i
= 0; i
< GetNcolours(frame
); i
++)
140 if ((pal
[3 * i
+ 0] == 255) &&
141 (pal
[3 * i
+ 1] == 0) &&
142 (pal
[3 * i
+ 2] == 255))
144 pal
[3 * i
+ 2] = 254;
148 pal
[3 * transparent
+ 0] = 255,
149 pal
[3 * transparent
+ 1] = 0,
150 pal
[3 * transparent
+ 2] = 255;
152 image
->SetMaskColour(255, 0, 255);
155 image
->SetMask(false);
158 unsigned char r
[256];
159 unsigned char g
[256];
160 unsigned char b
[256];
162 for (i
= 0; i
< 256; i
++)
169 image
->SetPalette(wxPalette(GetNcolours(frame
), r
, g
, b
));
170 #endif // wxUSE_PALETTE
173 unsigned long npixel
= sz
.GetWidth() * sz
.GetHeight();
174 for (i
= 0; i
< npixel
; i
++, src
++)
176 *(dst
++) = pal
[3 * (*src
) + 0];
177 *(dst
++) = pal
[3 * (*src
) + 1];
178 *(dst
++) = pal
[3 * (*src
) + 2];
185 //---------------------------------------------------------------------------
187 //---------------------------------------------------------------------------
189 #define GetFrame(n) ((GIFImage*)m_frames[n])
192 // Get data for current frame
194 wxSize
wxGIFDecoder::GetFrameSize(unsigned int frame
) const
196 return wxSize(GetFrame(frame
)->w
, GetFrame(frame
)->h
);
199 wxPoint
wxGIFDecoder::GetFramePosition(unsigned int frame
) const
201 return wxPoint(GetFrame(frame
)->left
, GetFrame(frame
)->top
);
204 wxAnimationDisposal
wxGIFDecoder::GetDisposalMethod(unsigned int frame
) const
206 return GetFrame(frame
)->disposal
;
209 long wxGIFDecoder::GetDelay(unsigned int frame
) const
211 return GetFrame(frame
)->delay
;
214 wxColour
wxGIFDecoder::GetTransparentColour(unsigned int frame
) const
216 unsigned char *pal
= GetFrame(frame
)->pal
;
217 int n
= GetFrame(frame
)->transparent
;
221 return wxColour(pal
[n
*3 + 0],
226 unsigned char* wxGIFDecoder::GetData(unsigned int frame
) const { return (GetFrame(frame
)->p
); }
227 unsigned char* wxGIFDecoder::GetPalette(unsigned int frame
) const { return (GetFrame(frame
)->pal
); }
228 unsigned int wxGIFDecoder::GetNcolours(unsigned int frame
) const { return (GetFrame(frame
)->ncolours
); }
229 int wxGIFDecoder::GetTransparentColourIndex(unsigned int frame
) const { return (GetFrame(frame
)->transparent
); }
233 //---------------------------------------------------------------------------
234 // GIF reading and decoding
235 //---------------------------------------------------------------------------
238 // Reads the next code from the file stream, with size 'bits'
240 int wxGIFDecoder::getcode(wxInputStream
& stream
, int bits
, int ab_fin
)
242 unsigned int mask
; // bit mask
243 unsigned int code
; // code (result)
245 // get remaining bits from last byte read
246 mask
= (1 << bits
) - 1;
247 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
249 // keep reading new bytes while needed
250 while (bits
> m_restbits
)
252 // if no bytes left in this block, read the next block
255 m_restbyte
= (unsigned char)stream
.GetC();
257 /* Some encoders are a bit broken: instead of issuing
258 * an end-of-image symbol (ab_fin) they come up with
259 * a zero-length subblock!! We catch this here so
260 * that the decoder sees an ab_fin code.
269 stream
.Read((void *) m_buffer
, m_restbyte
);
270 if (stream
.LastRead() != m_restbyte
)
278 // read next byte and isolate the bits we need
279 m_lastbyte
= (unsigned char) (*m_bufp
++);
280 mask
= (1 << (bits
- m_restbits
)) - 1;
281 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
284 // adjust total number of bits extracted from the buffer
285 m_restbits
= m_restbits
+ 8;
288 // find number of bits remaining for next code
289 m_restbits
= (m_restbits
- bits
);
296 // GIF decoding function. The initial code size (aka root size)
297 // is 'bits'. Supports interlaced images (interl == 1).
298 // Returns wxGIF_OK (== 0) on success, or an error code if something
299 // fails (see header file for details)
301 wxGIFDecoder::dgif(wxInputStream
& stream
, GIFImage
*img
, int interl
, int bits
)
303 static const int allocSize
= 4096 + 1;
304 int *ab_prefix
= new int[allocSize
]; // alphabet (prefixes)
305 if (ab_prefix
== NULL
)
310 int *ab_tail
= new int[allocSize
]; // alphabet (tails)
317 int *stack
= new int[allocSize
]; // decompression stack
325 int ab_clr
; // clear code
326 int ab_fin
; // end of info code
327 int ab_bits
; // actual symbol width, in bits
328 int ab_free
; // first free position in alphabet
329 int ab_max
; // last possible character in alphabet
330 int pass
; // pass number in interlaced images
331 int pos
; // index into decompresion stack
332 unsigned int x
, y
; // position in image buffer
334 int code
, readcode
, lastcode
, abcabca
;
336 // these won't change
337 ab_clr
= (1 << bits
);
338 ab_fin
= (1 << bits
) + 1;
340 // these will change through the decompression proccess
342 ab_free
= (1 << bits
) + 2;
343 ab_max
= (1 << ab_bits
) - 1;
349 // reset decoder vars
357 readcode
= code
= getcode(stream
, ab_bits
, ab_fin
);
360 if (code
== ab_fin
) break;
365 // reset main variables
367 ab_free
= (1 << bits
) + 2;
368 ab_max
= (1 << ab_bits
) - 1;
376 // unknown code: special case (like in ABCABCA)
379 code
= lastcode
; // take last string
380 stack
[pos
++] = abcabca
; // add first character
383 // build the string for this code in the stack
384 while (code
> ab_clr
)
386 stack
[pos
++] = ab_tail
[code
];
387 code
= ab_prefix
[code
];
389 // Don't overflow. This shouldn't happen with normal
390 // GIF files, the allocSize of 4096+1 is enough. This
391 // will only happen with badly formed GIFs.
392 if (pos
>= allocSize
)
397 return wxGIF_INVFORMAT
;
401 if (pos
>= allocSize
)
406 return wxGIF_INVFORMAT
;
409 stack
[pos
] = code
; // push last code into the stack
410 abcabca
= code
; // save for special case
412 // make new entry in alphabet (only if NOT just cleared)
415 // Normally, after the alphabet is full and can't grow any
416 // further (ab_free == 4096), encoder should (must?) emit CLEAR
417 // to reset it. This checks whether we really got it, otherwise
418 // the GIF is damaged.
419 if (ab_free
> ab_max
)
424 return wxGIF_INVFORMAT
;
427 // This assert seems unnecessary since the condition above
428 // eliminates the only case in which it went false. But I really
429 // don't like being forced to ask "Who in .text could have
430 // written there?!" And I wouldn't have been forced to ask if
431 // this line had already been here.
432 wxASSERT(ab_free
< allocSize
);
434 ab_prefix
[ab_free
] = lastcode
;
435 ab_tail
[ab_free
] = code
;
438 if ((ab_free
> ab_max
) && (ab_bits
< 12))
441 ab_max
= (1 << ab_bits
) - 1;
445 // dump stack data to the image buffer
448 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
457 // support for interlaced images
460 case 1: y
+= 8; break;
461 case 2: y
+= 8; break;
462 case 3: y
+= 4; break;
463 case 4: y
+= 2; break;
466 /* loop until a valid y coordinate has been
467 found, Or if the maximum number of passes has
468 been reached, exit the loop, and stop image
469 decoding (At this point the image is successfully
471 If we don't loop, but merely set y to some other
472 value, that new value might still be invalid depending
473 on the height of the image. This would cause out of
476 while (y
>= (img
->h
))
480 case 2: y
= 4; break;
481 case 3: y
= 2; break;
482 case 4: y
= 1; break;
486 It's possible we arrive here. For example this
487 happens when the image is interlaced, and the
488 height is 1. Looking at the above cases, the
489 lowest possible y is 1. While the only valid
490 one would be 0 for an image of height 1. So
491 'eventually' the loop will arrive here.
492 This case makes sure this while loop is
493 exited, as well as the 2 other ones.
496 // Set y to a valid coordinate so the local
497 // while loop will be exited. (y = 0 always
498 // is >= img->h since if img->h == 0 the
499 // image is never decoded)
502 // This will exit the other outer while loop
505 // This will halt image decoding.
517 Normally image decoding is finished when an End of Information code is
518 encountered (code == ab_fin) however some broken encoders write wrong
519 "block byte counts" (The first byte value after the "code size" byte),
520 being one value too high. It might very well be possible other variants
521 of this problem occur as well. The only sensible solution seems to
522 be to check for clipping.
523 Example of wrong encoding:
524 (1 * 1 B/W image, raster data stream follows in hex bytes)
526 02 << B/W images have a code size of 2
527 02 << Block byte count
529 00 << Zero byte count (terminates data stream)
531 Because the block byte count is 2, the zero byte count is used in the
532 decoding process, and decoding is continued after this byte. (While it
533 should signal an end of image)
539 01 << When decoded this correctly includes the End of Information code
547 (The 44 doesn't include an End of Information code, but at least the
548 decoder correctly skips to 00 now after decoding, and signals this
549 as an End of Information itself)
563 while (code
!= ab_fin
);
565 delete [] ab_prefix
;
574 // Returns true if the file looks like a valid GIF, false otherwise.
576 bool wxGIFDecoder::CanRead(wxInputStream
&stream
) const
578 unsigned char buf
[3];
580 if ( !stream
.Read(buf
, WXSIZEOF(buf
)) )
583 if (stream
.SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
) == wxInvalidOffset
)
584 return false; // this happens e.g. for non-seekable streams
586 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
591 // Reads and decodes one or more GIF images, depending on whether
592 // animated GIF support is enabled. Can read GIFs with any bit
593 // size (color depth), but the output images are always expanded
594 // to 8 bits per pixel. Also, the image palettes always contain
595 // 256 colors, although some of them may be unused. Returns wxGIF_OK
596 // (== 0) on success, or an error code if something fails (see
597 // header file for details)
599 wxGIFErrorCode
wxGIFDecoder::LoadGIF(wxInputStream
& stream
)
601 unsigned int global_ncolors
= 0;
603 wxAnimationDisposal disposal
;
606 unsigned char type
= 0;
607 unsigned char pal
[768];
608 unsigned char buf
[16];
611 // check GIF signature
612 if (!CanRead(stream
))
613 return wxGIF_INVFORMAT
;
615 // check for animated GIF support (ver. >= 89a)
617 static const unsigned int headerSize
= (3 + 3);
618 stream
.Read(buf
, headerSize
);
619 if (stream
.LastRead() != headerSize
)
621 return wxGIF_INVFORMAT
;
624 if (memcmp(buf
+ 3, "89a", 3) < 0)
629 // read logical screen descriptor block (LSDB)
630 static const unsigned int lsdbSize
= (2 + 2 + 1 + 1 + 1);
631 stream
.Read(buf
, lsdbSize
);
632 if (stream
.LastRead() != lsdbSize
)
634 return wxGIF_INVFORMAT
;
637 m_szAnimation
.SetWidth( buf
[0] + 256 * buf
[1] );
638 m_szAnimation
.SetHeight( buf
[2] + 256 * buf
[3] );
640 if (anim
&& ((m_szAnimation
.GetWidth() == 0) || (m_szAnimation
.GetHeight() == 0)))
642 return wxGIF_INVFORMAT
;
645 // load global color map if available
646 if ((buf
[4] & 0x80) == 0x80)
648 int backgroundColIndex
= buf
[5];
650 global_ncolors
= 2 << (buf
[4] & 0x07);
651 unsigned int numBytes
= 3 * global_ncolors
;
652 stream
.Read(pal
, numBytes
);
653 if (stream
.LastRead() != numBytes
)
655 return wxGIF_INVFORMAT
;
658 m_background
.Set(pal
[backgroundColIndex
*3 + 0],
659 pal
[backgroundColIndex
*3 + 1],
660 pal
[backgroundColIndex
*3 + 2]);
663 // transparent colour, disposal method and delay default to unused
664 int transparent
= -1;
665 disposal
= wxANIM_UNSPECIFIED
;
671 type
= (unsigned char)stream
.GetC();
674 If the end of file has been reached (or an error) and a ";"
675 (0x3B) hasn't been encountered yet, exit the loop. (Without this
676 check the while loop would loop endlessly.) Later on, in the next while
677 loop, the file will be treated as being truncated (But still
678 be decoded as far as possible). returning wxGIF_TRUNCATED is not
679 possible here since some init code is done after this loop.
681 if (stream
.Eof())// || !stream.IsOk())
684 type is set to some bogus value, so there's no
685 need to continue evaluating it.
687 break; // Alternative : "return wxGIF_INVFORMAT;"
699 if (((unsigned char)stream
.GetC()) == 0xF9)
700 // graphics control extension, parse it
702 static const unsigned int gceSize
= 6;
703 stream
.Read(buf
, gceSize
);
704 if (stream
.LastRead() != gceSize
)
707 return wxGIF_INVFORMAT
;
710 // read delay and convert from 1/100 of a second to ms
711 delay
= 10 * (buf
[2] + 256 * buf
[3]);
713 // read transparent colour index, if used
714 transparent
= buf
[1] & 0x01 ? buf
[4] : -1;
716 // read disposal method
717 disposal
= (wxAnimationDisposal
)(((buf
[1] & 0x1C) >> 2) - 1);
720 // other extension, skip
722 while ((i
= (unsigned char)stream
.GetC()) != 0)
724 if (stream
.Eof() || (stream
.LastRead() == 0) ||
725 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
734 // image descriptor block?
737 // allocate memory for IMAGEN struct
738 GIFImagePtr
pimg(new GIFImage());
740 wxScopeGuard guardDestroy
= wxMakeObjGuard(*this, &wxGIFDecoder::Destroy
);
746 static const unsigned int idbSize
= (2 + 2 + 2 + 2 + 1);
747 stream
.Read(buf
, idbSize
);
748 if (stream
.LastRead() != idbSize
)
749 return wxGIF_INVFORMAT
;
751 pimg
->left
= buf
[0] + 256 * buf
[1];
752 pimg
->top
= buf
[2] + 256 * buf
[3];
754 pimg->left = buf[4] + 256 * buf[5];
755 pimg->top = buf[4] + 256 * buf[5];
757 pimg
->w
= buf
[4] + 256 * buf
[5];
758 pimg
->h
= buf
[6] + 256 * buf
[7];
760 if ( anim
&& ((pimg
->w
== 0) || (pimg
->w
> (unsigned int)m_szAnimation
.GetWidth()) ||
761 (pimg
->h
== 0) || (pimg
->h
> (unsigned int)m_szAnimation
.GetHeight())) )
762 return wxGIF_INVFORMAT
;
764 interl
= ((buf
[8] & 0x40)? 1 : 0);
765 size
= pimg
->w
* pimg
->h
;
767 pimg
->transparent
= transparent
;
768 pimg
->disposal
= disposal
;
771 // allocate memory for image and palette
772 pimg
->p
= (unsigned char *) malloc((unsigned int)size
);
773 pimg
->pal
= (unsigned char *) malloc(768);
775 if ((!pimg
->p
) || (!pimg
->pal
))
778 // load local color map if available, else use global map
779 if ((buf
[8] & 0x80) == 0x80)
781 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
782 unsigned int numBytes
= 3 * local_ncolors
;
783 stream
.Read(pimg
->pal
, numBytes
);
784 pimg
->ncolours
= local_ncolors
;
785 if (stream
.LastRead() != numBytes
)
786 return wxGIF_INVFORMAT
;
790 memcpy(pimg
->pal
, pal
, 768);
791 pimg
->ncolours
= global_ncolors
;
794 // get initial code size from first byte in raster data
795 bits
= (unsigned char)stream
.GetC();
797 return wxGIF_INVFORMAT
;
800 wxGIFErrorCode result
= dgif(stream
, pimg
.get(), interl
, bits
);
801 if (result
!= wxGIF_OK
)
804 guardDestroy
.Dismiss();
806 // add the image to our frame array
807 m_frames
.Add(pimg
.release());
810 // if this is not an animated GIF, exit after first image
819 return wxGIF_INVFORMAT
;
822 // try to read to the end of the stream
826 return wxGIF_TRUNCATED
;
828 type
= (unsigned char)stream
.GetC();
833 (void) stream
.GetC();
836 while ((i
= (unsigned char)stream
.GetC()) != 0)
838 if (stream
.Eof() || (stream
.LastRead() == 0) ||
839 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
842 return wxGIF_INVFORMAT
;
846 else if (type
== 0x2C)
848 // image descriptor block
849 static const unsigned int idbSize
= (2 + 2 + 2 + 2 + 1);
850 stream
.Read(buf
, idbSize
);
851 if (stream
.LastRead() != idbSize
)
854 return wxGIF_INVFORMAT
;
858 if ((buf
[8] & 0x80) == 0x80)
860 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
861 wxFileOffset numBytes
= 3 * local_ncolors
;
862 if (stream
.SeekI(numBytes
, wxFromCurrent
) == wxInvalidOffset
)
865 return wxGIF_INVFORMAT
;
870 (void) stream
.GetC();
871 if (stream
.Eof() || (stream
.LastRead() == 0))
874 return wxGIF_INVFORMAT
;
878 while ((i
= (unsigned char)stream
.GetC()) != 0)
880 if (stream
.Eof() || (stream
.LastRead() == 0) ||
881 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
884 return wxGIF_INVFORMAT
;
888 else if ((type
!= 0x3B) && (type
!= 00)) // testing
890 // images are OK, but couldn't read to the end of the stream
891 return wxGIF_TRUNCATED
;
898 #endif // wxUSE_STREAMS && wxUSE_GIF