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"
28 #include "wx/gifdecod.h"
29 #include "wx/scopedptr.h"
30 #include "wx/scopeguard.h"
34 //---------------------------------------------------------------------------
36 //---------------------------------------------------------------------------
38 // internal class for storing GIF image data
45 unsigned int w
; // width
46 unsigned int h
; // height
47 unsigned int left
; // x coord (in logical screen)
48 unsigned int top
; // y coord (in logical screen)
49 int transparent
; // transparent color index (-1 = none)
50 wxAnimationDisposal disposal
; // disposal method
51 long delay
; // delay in ms (-1 = unused)
52 unsigned char *p
; // bitmap
53 unsigned char *pal
; // palette
54 unsigned int ncolours
; // number of colours
56 wxDECLARE_NO_COPY_CLASS(GIFImage
);
59 wxDECLARE_SCOPED_PTR(GIFImage
, GIFImagePtr
)
60 wxDEFINE_SCOPED_PTR(GIFImage
, GIFImagePtr
)
63 //---------------------------------------------------------------------------
64 // GIFImage constructor
65 //---------------------------------------------------------------------------
73 disposal
= wxANIM_DONOTREMOVE
;
75 p
= (unsigned char *) NULL
;
76 pal
= (unsigned char *) NULL
;
80 //---------------------------------------------------------------------------
81 // wxGIFDecoder constructor and destructor
82 //---------------------------------------------------------------------------
84 wxGIFDecoder::wxGIFDecoder()
88 wxGIFDecoder::~wxGIFDecoder()
93 void wxGIFDecoder::Destroy()
95 wxASSERT(m_nFrames
==m_frames
.GetCount());
96 for (unsigned int i
=0; i
<m_nFrames
; i
++)
98 GIFImage
*f
= (GIFImage
*)m_frames
[i
];
109 //---------------------------------------------------------------------------
110 // Convert this image to a wxImage object
111 //---------------------------------------------------------------------------
113 // This function was designed by Vaclav Slavik
115 bool wxGIFDecoder::ConvertToImage(unsigned int frame
, wxImage
*image
) const
117 unsigned char *src
, *dst
, *pal
;
125 wxSize sz
= GetFrameSize(frame
);
126 image
->Create(sz
.GetWidth(), sz
.GetHeight());
127 image
->SetType(wxBITMAP_TYPE_GIF
);
132 pal
= GetPalette(frame
);
133 src
= GetData(frame
);
134 dst
= image
->GetData();
135 transparent
= GetTransparentColourIndex(frame
);
137 // set transparent colour mask
138 if (transparent
!= -1)
140 for (i
= 0; i
< GetNcolours(frame
); i
++)
142 if ((pal
[3 * i
+ 0] == 255) &&
143 (pal
[3 * i
+ 1] == 0) &&
144 (pal
[3 * i
+ 2] == 255))
146 pal
[3 * i
+ 2] = 254;
150 pal
[3 * transparent
+ 0] = 255,
151 pal
[3 * transparent
+ 1] = 0,
152 pal
[3 * transparent
+ 2] = 255;
154 image
->SetMaskColour(255, 0, 255);
157 image
->SetMask(false);
160 unsigned char r
[256];
161 unsigned char g
[256];
162 unsigned char b
[256];
164 for (i
= 0; i
< 256; i
++)
171 image
->SetPalette(wxPalette(GetNcolours(frame
), r
, g
, b
));
172 #endif // wxUSE_PALETTE
175 unsigned long npixel
= sz
.GetWidth() * sz
.GetHeight();
176 for (i
= 0; i
< npixel
; i
++, src
++)
178 *(dst
++) = pal
[3 * (*src
) + 0];
179 *(dst
++) = pal
[3 * (*src
) + 1];
180 *(dst
++) = pal
[3 * (*src
) + 2];
187 //---------------------------------------------------------------------------
189 //---------------------------------------------------------------------------
191 #define GetFrame(n) ((GIFImage*)m_frames[n])
194 // Get data for current frame
196 wxSize
wxGIFDecoder::GetFrameSize(unsigned int frame
) const
198 return wxSize(GetFrame(frame
)->w
, GetFrame(frame
)->h
);
201 wxPoint
wxGIFDecoder::GetFramePosition(unsigned int frame
) const
203 return wxPoint(GetFrame(frame
)->left
, GetFrame(frame
)->top
);
206 wxAnimationDisposal
wxGIFDecoder::GetDisposalMethod(unsigned int frame
) const
208 return GetFrame(frame
)->disposal
;
211 long wxGIFDecoder::GetDelay(unsigned int frame
) const
213 return GetFrame(frame
)->delay
;
216 wxColour
wxGIFDecoder::GetTransparentColour(unsigned int frame
) const
218 unsigned char *pal
= GetFrame(frame
)->pal
;
219 int n
= GetFrame(frame
)->transparent
;
223 return wxColour(pal
[n
*3 + 0],
228 unsigned char* wxGIFDecoder::GetData(unsigned int frame
) const { return (GetFrame(frame
)->p
); }
229 unsigned char* wxGIFDecoder::GetPalette(unsigned int frame
) const { return (GetFrame(frame
)->pal
); }
230 unsigned int wxGIFDecoder::GetNcolours(unsigned int frame
) const { return (GetFrame(frame
)->ncolours
); }
231 int wxGIFDecoder::GetTransparentColourIndex(unsigned int frame
) const { return (GetFrame(frame
)->transparent
); }
235 //---------------------------------------------------------------------------
236 // GIF reading and decoding
237 //---------------------------------------------------------------------------
240 // Reads the next code from the file stream, with size 'bits'
242 int wxGIFDecoder::getcode(wxInputStream
& stream
, int bits
, int ab_fin
)
244 unsigned int mask
; // bit mask
245 unsigned int code
; // code (result)
247 // get remaining bits from last byte read
248 mask
= (1 << bits
) - 1;
249 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
251 // keep reading new bytes while needed
252 while (bits
> m_restbits
)
254 // if no bytes left in this block, read the next block
257 m_restbyte
= (unsigned char)stream
.GetC();
259 /* Some encoders are a bit broken: instead of issuing
260 * an end-of-image symbol (ab_fin) they come up with
261 * a zero-length subblock!! We catch this here so
262 * that the decoder sees an ab_fin code.
271 stream
.Read((void *) m_buffer
, m_restbyte
);
272 if (stream
.LastRead() != m_restbyte
)
280 // read next byte and isolate the bits we need
281 m_lastbyte
= (unsigned char) (*m_bufp
++);
282 mask
= (1 << (bits
- m_restbits
)) - 1;
283 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
286 // adjust total number of bits extracted from the buffer
287 m_restbits
= m_restbits
+ 8;
290 // find number of bits remaining for next code
291 m_restbits
= (m_restbits
- bits
);
298 // GIF decoding function. The initial code size (aka root size)
299 // is 'bits'. Supports interlaced images (interl == 1).
300 // Returns wxGIF_OK (== 0) on success, or an error code if something
301 // fails (see header file for details)
303 wxGIFDecoder::dgif(wxInputStream
& stream
, GIFImage
*img
, int interl
, int bits
)
305 static const int allocSize
= 4096 + 1;
306 int *ab_prefix
= new int[allocSize
]; // alphabet (prefixes)
307 if (ab_prefix
== NULL
)
312 int *ab_tail
= new int[allocSize
]; // alphabet (tails)
319 int *stack
= new int[allocSize
]; // decompression stack
327 int ab_clr
; // clear code
328 int ab_fin
; // end of info code
329 int ab_bits
; // actual symbol width, in bits
330 int ab_free
; // first free position in alphabet
331 int ab_max
; // last possible character in alphabet
332 int pass
; // pass number in interlaced images
333 int pos
; // index into decompresion stack
334 unsigned int x
, y
; // position in image buffer
336 int code
, readcode
, lastcode
, abcabca
;
338 // these won't change
339 ab_clr
= (1 << bits
);
340 ab_fin
= (1 << bits
) + 1;
342 // these will change through the decompression proccess
344 ab_free
= (1 << bits
) + 2;
345 ab_max
= (1 << ab_bits
) - 1;
351 // reset decoder vars
359 readcode
= code
= getcode(stream
, ab_bits
, ab_fin
);
362 if (code
== ab_fin
) break;
367 // reset main variables
369 ab_free
= (1 << bits
) + 2;
370 ab_max
= (1 << ab_bits
) - 1;
378 // unknown code: special case (like in ABCABCA)
381 code
= lastcode
; // take last string
382 stack
[pos
++] = abcabca
; // add first character
385 // build the string for this code in the stack
386 while (code
> ab_clr
)
388 stack
[pos
++] = ab_tail
[code
];
389 code
= ab_prefix
[code
];
391 // Don't overflow. This shouldn't happen with normal
392 // GIF files, the allocSize of 4096+1 is enough. This
393 // will only happen with badly formed GIFs.
394 if (pos
>= allocSize
)
399 return wxGIF_INVFORMAT
;
403 if (pos
>= allocSize
)
408 return wxGIF_INVFORMAT
;
411 stack
[pos
] = code
; // push last code into the stack
412 abcabca
= code
; // save for special case
414 // make new entry in alphabet (only if NOT just cleared)
417 // Normally, after the alphabet is full and can't grow any
418 // further (ab_free == 4096), encoder should (must?) emit CLEAR
419 // to reset it. This checks whether we really got it, otherwise
420 // the GIF is damaged.
421 if (ab_free
> ab_max
)
426 return wxGIF_INVFORMAT
;
429 // This assert seems unnecessary since the condition above
430 // eliminates the only case in which it went false. But I really
431 // don't like being forced to ask "Who in .text could have
432 // written there?!" And I wouldn't have been forced to ask if
433 // this line had already been here.
434 wxASSERT(ab_free
< allocSize
);
436 ab_prefix
[ab_free
] = lastcode
;
437 ab_tail
[ab_free
] = code
;
440 if ((ab_free
> ab_max
) && (ab_bits
< 12))
443 ab_max
= (1 << ab_bits
) - 1;
447 // dump stack data to the image buffer
450 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
459 // support for interlaced images
462 case 1: y
+= 8; break;
463 case 2: y
+= 8; break;
464 case 3: y
+= 4; break;
465 case 4: y
+= 2; break;
468 /* loop until a valid y coordinate has been
469 found, Or if the maximum number of passes has
470 been reached, exit the loop, and stop image
471 decoding (At this point the image is successfully
473 If we don't loop, but merely set y to some other
474 value, that new value might still be invalid depending
475 on the height of the image. This would cause out of
478 while (y
>= (img
->h
))
482 case 2: y
= 4; break;
483 case 3: y
= 2; break;
484 case 4: y
= 1; break;
488 It's possible we arrive here. For example this
489 happens when the image is interlaced, and the
490 height is 1. Looking at the above cases, the
491 lowest possible y is 1. While the only valid
492 one would be 0 for an image of height 1. So
493 'eventually' the loop will arrive here.
494 This case makes sure this while loop is
495 exited, as well as the 2 other ones.
498 // Set y to a valid coordinate so the local
499 // while loop will be exited. (y = 0 always
500 // is >= img->h since if img->h == 0 the
501 // image is never decoded)
504 // This will exit the other outer while loop
507 // This will halt image decoding.
519 Normally image decoding is finished when an End of Information code is
520 encountered (code == ab_fin) however some broken encoders write wrong
521 "block byte counts" (The first byte value after the "code size" byte),
522 being one value too high. It might very well be possible other variants
523 of this problem occur as well. The only sensible solution seems to
524 be to check for clipping.
525 Example of wrong encoding:
526 (1 * 1 B/W image, raster data stream follows in hex bytes)
528 02 << B/W images have a code size of 2
529 02 << Block byte count
531 00 << Zero byte count (terminates data stream)
533 Because the block byte count is 2, the zero byte count is used in the
534 decoding process, and decoding is continued after this byte. (While it
535 should signal an end of image)
541 01 << When decoded this correctly includes the End of Information code
549 (The 44 doesn't include an End of Information code, but at least the
550 decoder correctly skips to 00 now after decoding, and signals this
551 as an End of Information itself)
565 while (code
!= ab_fin
);
567 delete [] ab_prefix
;
576 // Returns true if the file looks like a valid GIF, false otherwise.
578 bool wxGIFDecoder::DoCanRead(wxInputStream
&stream
) const
580 unsigned char buf
[3];
582 if ( !stream
.Read(buf
, WXSIZEOF(buf
)) )
585 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
590 // Reads and decodes one or more GIF images, depending on whether
591 // animated GIF support is enabled. Can read GIFs with any bit
592 // size (color depth), but the output images are always expanded
593 // to 8 bits per pixel. Also, the image palettes always contain
594 // 256 colors, although some of them may be unused. Returns wxGIF_OK
595 // (== 0) on success, or an error code if something fails (see
596 // header file for details)
598 wxGIFErrorCode
wxGIFDecoder::LoadGIF(wxInputStream
& stream
)
600 unsigned int global_ncolors
= 0;
602 wxAnimationDisposal disposal
;
605 unsigned char type
= 0;
606 unsigned char pal
[768];
607 unsigned char buf
[16];
610 // check GIF signature
611 if (!CanRead(stream
))
612 return wxGIF_INVFORMAT
;
614 // check for animated GIF support (ver. >= 89a)
616 static const unsigned int headerSize
= (3 + 3);
617 stream
.Read(buf
, headerSize
);
618 if (stream
.LastRead() != headerSize
)
620 return wxGIF_INVFORMAT
;
623 if (memcmp(buf
+ 3, "89a", 3) < 0)
628 // read logical screen descriptor block (LSDB)
629 static const unsigned int lsdbSize
= (2 + 2 + 1 + 1 + 1);
630 stream
.Read(buf
, lsdbSize
);
631 if (stream
.LastRead() != lsdbSize
)
633 return wxGIF_INVFORMAT
;
636 m_szAnimation
.SetWidth( buf
[0] + 256 * buf
[1] );
637 m_szAnimation
.SetHeight( buf
[2] + 256 * buf
[3] );
639 if (anim
&& ((m_szAnimation
.GetWidth() == 0) || (m_szAnimation
.GetHeight() == 0)))
641 return wxGIF_INVFORMAT
;
644 // load global color map if available
645 if ((buf
[4] & 0x80) == 0x80)
647 int backgroundColIndex
= buf
[5];
649 global_ncolors
= 2 << (buf
[4] & 0x07);
650 unsigned int numBytes
= 3 * global_ncolors
;
651 stream
.Read(pal
, numBytes
);
652 if (stream
.LastRead() != numBytes
)
654 return wxGIF_INVFORMAT
;
657 m_background
.Set(pal
[backgroundColIndex
*3 + 0],
658 pal
[backgroundColIndex
*3 + 1],
659 pal
[backgroundColIndex
*3 + 2]);
662 // transparent colour, disposal method and delay default to unused
663 int transparent
= -1;
664 disposal
= wxANIM_UNSPECIFIED
;
670 type
= (unsigned char)stream
.GetC();
673 If the end of file has been reached (or an error) and a ";"
674 (0x3B) hasn't been encountered yet, exit the loop. (Without this
675 check the while loop would loop endlessly.) Later on, in the next while
676 loop, the file will be treated as being truncated (But still
677 be decoded as far as possible). returning wxGIF_TRUNCATED is not
678 possible here since some init code is done after this loop.
680 if (stream
.Eof())// || !stream.IsOk())
683 type is set to some bogus value, so there's no
684 need to continue evaluating it.
686 break; // Alternative : "return wxGIF_INVFORMAT;"
698 if (((unsigned char)stream
.GetC()) == 0xF9)
699 // graphics control extension, parse it
701 static const unsigned int gceSize
= 6;
702 stream
.Read(buf
, gceSize
);
703 if (stream
.LastRead() != gceSize
)
706 return wxGIF_INVFORMAT
;
709 // read delay and convert from 1/100 of a second to ms
710 delay
= 10 * (buf
[2] + 256 * buf
[3]);
712 // read transparent colour index, if used
713 transparent
= buf
[1] & 0x01 ? buf
[4] : -1;
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) ||
724 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
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];
761 // some GIF images specify incorrect animation size but we can
762 // still open them if we fix up the animation size, see #9465
763 if ( m_nFrames
== 0 )
765 if ( pimg
->w
> (unsigned)m_szAnimation
.x
)
766 m_szAnimation
.x
= pimg
->w
;
767 if ( pimg
->h
> (unsigned)m_szAnimation
.y
)
768 m_szAnimation
.y
= pimg
->h
;
770 else // subsequent frames
772 // check that we have valid size
773 if ( (!pimg
->w
|| pimg
->w
> (unsigned)m_szAnimation
.x
) ||
774 (!pimg
->h
|| pimg
->h
> (unsigned)m_szAnimation
.y
) )
776 wxLogError(_("Incorrect GIF frame size (%u, %d) for "
778 pimg
->w
, pimg
->h
, m_nFrames
);
779 return wxGIF_INVFORMAT
;
784 interl
= ((buf
[8] & 0x40)? 1 : 0);
785 size
= pimg
->w
* pimg
->h
;
787 pimg
->transparent
= transparent
;
788 pimg
->disposal
= disposal
;
791 // allocate memory for image and palette
792 pimg
->p
= (unsigned char *) malloc((unsigned int)size
);
793 pimg
->pal
= (unsigned char *) malloc(768);
795 if ((!pimg
->p
) || (!pimg
->pal
))
798 // load local color map if available, else use global map
799 if ((buf
[8] & 0x80) == 0x80)
801 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
802 unsigned int numBytes
= 3 * local_ncolors
;
803 stream
.Read(pimg
->pal
, numBytes
);
804 pimg
->ncolours
= local_ncolors
;
805 if (stream
.LastRead() != numBytes
)
806 return wxGIF_INVFORMAT
;
810 memcpy(pimg
->pal
, pal
, 768);
811 pimg
->ncolours
= global_ncolors
;
814 // get initial code size from first byte in raster data
815 bits
= (unsigned char)stream
.GetC();
817 return wxGIF_INVFORMAT
;
820 wxGIFErrorCode result
= dgif(stream
, pimg
.get(), interl
, bits
);
821 if (result
!= wxGIF_OK
)
824 guardDestroy
.Dismiss();
826 // add the image to our frame array
827 m_frames
.Add(pimg
.release());
830 // if this is not an animated GIF, exit after first image
839 return wxGIF_INVFORMAT
;
842 // try to read to the end of the stream
846 return wxGIF_TRUNCATED
;
848 type
= (unsigned char)stream
.GetC();
853 (void) stream
.GetC();
856 while ((i
= (unsigned char)stream
.GetC()) != 0)
858 if (stream
.Eof() || (stream
.LastRead() == 0) ||
859 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
862 return wxGIF_INVFORMAT
;
866 else if (type
== 0x2C)
868 // image descriptor block
869 static const unsigned int idbSize
= (2 + 2 + 2 + 2 + 1);
870 stream
.Read(buf
, idbSize
);
871 if (stream
.LastRead() != idbSize
)
874 return wxGIF_INVFORMAT
;
878 if ((buf
[8] & 0x80) == 0x80)
880 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
881 wxFileOffset numBytes
= 3 * local_ncolors
;
882 if (stream
.SeekI(numBytes
, wxFromCurrent
) == wxInvalidOffset
)
885 return wxGIF_INVFORMAT
;
890 (void) stream
.GetC();
891 if (stream
.Eof() || (stream
.LastRead() == 0))
894 return wxGIF_INVFORMAT
;
898 while ((i
= (unsigned char)stream
.GetC()) != 0)
900 if (stream
.Eof() || (stream
.LastRead() == 0) ||
901 stream
.SeekI(i
, wxFromCurrent
) == wxInvalidOffset
)
904 return wxGIF_INVFORMAT
;
908 else if ((type
!= 0x3B) && (type
!= 00)) // testing
910 // images are OK, but couldn't read to the end of the stream
911 return wxGIF_TRUNCATED
;
918 #endif // wxUSE_STREAMS && wxUSE_GIF