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"
30 //---------------------------------------------------------------------------
32 //---------------------------------------------------------------------------
34 // internal class for storing GIF image data
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 */
52 DECLARE_NO_COPY_CLASS(GIFImage
)
57 //---------------------------------------------------------------------------
58 // GIFImage constructor
59 //---------------------------------------------------------------------------
67 disposal
= wxANIM_DONOTREMOVE
;
69 p
= (unsigned char *) NULL
;
70 pal
= (unsigned char *) NULL
;
74 //---------------------------------------------------------------------------
75 // wxGIFDecoder constructor and destructor
76 //---------------------------------------------------------------------------
78 wxGIFDecoder::wxGIFDecoder()
82 wxGIFDecoder::~wxGIFDecoder()
87 void wxGIFDecoder::Destroy()
89 wxASSERT(m_nFrames
==m_frames
.GetCount());
90 for (size_t i
=0; i
<m_nFrames
; i
++)
92 GIFImage
*f
= (GIFImage
*)m_frames
[i
];
103 //---------------------------------------------------------------------------
104 // Convert this image to a wxImage object
105 //---------------------------------------------------------------------------
107 // This function was designed by Vaclav Slavik
109 bool wxGIFDecoder::ConvertToImage(size_t frame
, wxImage
*image
) const
111 unsigned char *src
, *dst
, *pal
;
115 /* just in case... */
118 /* create the image */
119 wxSize sz
= GetFrameSize(frame
);
120 image
->Create(sz
.GetWidth(), sz
.GetHeight());
125 pal
= GetPalette(frame
);
126 src
= GetData(frame
);
127 dst
= image
->GetData();
128 transparent
= GetTransparentColour(frame
);
130 /* set transparent colour mask */
131 if (transparent
!= -1)
133 for (i
= 0; i
< GetNcolours(frame
); i
++)
135 if ((pal
[3 * i
+ 0] == 255) &&
136 (pal
[3 * i
+ 1] == 0) &&
137 (pal
[3 * i
+ 2] == 255))
139 pal
[3 * i
+ 2] = 254;
143 pal
[3 * transparent
+ 0] = 255,
144 pal
[3 * transparent
+ 1] = 0,
145 pal
[3 * transparent
+ 2] = 255;
147 image
->SetMaskColour(255, 0, 255);
150 image
->SetMask(false);
153 unsigned char r
[256];
154 unsigned char g
[256];
155 unsigned char b
[256];
157 for (i
= 0; i
< 256; i
++)
164 image
->SetPalette(wxPalette(GetNcolours(frame
), r
, g
, b
));
165 #endif // wxUSE_PALETTE
167 /* copy image data */
168 unsigned long npixel
= sz
.GetWidth() * sz
.GetHeight();
169 for (i
= 0; i
< npixel
; i
++, src
++)
171 *(dst
++) = pal
[3 * (*src
) + 0];
172 *(dst
++) = pal
[3 * (*src
) + 1];
173 *(dst
++) = pal
[3 * (*src
) + 2];
180 //---------------------------------------------------------------------------
182 //---------------------------------------------------------------------------
184 #define GetFrame(n) ((GIFImage*)m_frames[n])
187 // Get data for current frame
189 wxSize
wxGIFDecoder::GetFrameSize(size_t frame
) const
191 return wxSize(GetFrame(frame
)->w
, GetFrame(frame
)->h
);
194 wxPoint
wxGIFDecoder::GetFramePosition(size_t frame
) const
196 return wxPoint(GetFrame(frame
)->left
, GetFrame(frame
)->top
);
199 wxAnimationDisposal
wxGIFDecoder::GetDisposalMethod(size_t frame
) const
201 return GetFrame(frame
)->disposal
;
204 long wxGIFDecoder::GetDelay(size_t frame
) const
206 return GetFrame(frame
)->delay
;
209 unsigned char* wxGIFDecoder::GetData(size_t frame
) const { return (GetFrame(frame
)->p
); }
210 unsigned char* wxGIFDecoder::GetPalette(size_t frame
) const { return (GetFrame(frame
)->pal
); }
211 unsigned int wxGIFDecoder::GetNcolours(size_t frame
) const { return (GetFrame(frame
)->ncolours
); }
212 int wxGIFDecoder::GetTransparentColour(size_t frame
) const { return (GetFrame(frame
)->transparent
); }
216 //---------------------------------------------------------------------------
217 // GIF reading and decoding
218 //---------------------------------------------------------------------------
221 // Reads the next code from the file stream, with size 'bits'
223 int wxGIFDecoder::getcode(wxInputStream
& stream
, int bits
, int ab_fin
)
225 unsigned int mask
; /* bit mask */
226 unsigned int code
; /* code (result) */
228 /* get remaining bits from last byte read */
229 mask
= (1 << bits
) - 1;
230 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
232 /* keep reading new bytes while needed */
233 while (bits
> m_restbits
)
235 /* if no bytes left in this block, read the next block */
238 m_restbyte
= (unsigned char)stream
.GetC();
240 /* Some encoders are a bit broken: instead of issuing
241 * an end-of-image symbol (ab_fin) they come up with
242 * a zero-length subblock!! We catch this here so
243 * that the decoder sees an ab_fin code.
252 stream
.Read((void *) m_buffer
, m_restbyte
);
253 if (stream
.LastRead() != m_restbyte
)
261 /* read next byte and isolate the bits we need */
262 m_lastbyte
= (unsigned char) (*m_bufp
++);
263 mask
= (1 << (bits
- m_restbits
)) - 1;
264 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
267 /* adjust total number of bits extracted from the buffer */
268 m_restbits
= m_restbits
+ 8;
271 /* find number of bits remaining for next code */
272 m_restbits
= (m_restbits
- bits
);
279 // GIF decoding function. The initial code size (aka root size)
280 // is 'bits'. Supports interlaced images (interl == 1).
281 // Returns wxGIF_OK (== 0) on success, or an error code if something
282 // fails (see header file for details)
283 wxGIFErrorCode
wxGIFDecoder::dgif(wxInputStream
& stream
, GIFImage
*img
, int interl
, int bits
)
285 static const int allocSize
= 4096 + 1;
286 int *ab_prefix
= new int[allocSize
]; /* alphabet (prefixes) */
287 if (ab_prefix
== NULL
)
292 int *ab_tail
= new int[allocSize
]; /* alphabet (tails) */
299 int *stack
= new int[allocSize
]; /* decompression stack */
307 int ab_clr
; /* clear code */
308 int ab_fin
; /* end of info code */
309 int ab_bits
; /* actual symbol width, in bits */
310 int ab_free
; /* first free position in alphabet */
311 int ab_max
; /* last possible character in alphabet */
312 int pass
; /* pass number in interlaced images */
313 int pos
; /* index into decompresion stack */
314 unsigned int x
, y
; /* position in image buffer */
316 int code
, readcode
, lastcode
, abcabca
;
318 /* these won't change */
319 ab_clr
= (1 << bits
);
320 ab_fin
= (1 << bits
) + 1;
322 /* these will change through the decompression proccess */
324 ab_free
= (1 << bits
) + 2;
325 ab_max
= (1 << ab_bits
) - 1;
331 /* reset decoder vars */
339 readcode
= code
= getcode(stream
, ab_bits
, ab_fin
);
342 if (code
== ab_fin
) break;
344 /* reset alphabet? */
347 /* reset main variables */
349 ab_free
= (1 << bits
) + 2;
350 ab_max
= (1 << ab_bits
) - 1;
354 /* skip to next code */
358 /* unknown code: special case (like in ABCABCA) */
361 code
= lastcode
; /* take last string */
362 stack
[pos
++] = abcabca
; /* add first character */
365 /* build the string for this code in the stack */
366 while (code
> ab_clr
)
368 stack
[pos
++] = ab_tail
[code
];
369 code
= ab_prefix
[code
];
371 // Don't overflow. This shouldn't happen with normal
372 // GIF files, the allocSize of 4096+1 is enough. This
373 // will only happen with badly formed GIFs.
374 if (pos
>= allocSize
)
379 return wxGIF_INVFORMAT
;
383 if (pos
>= allocSize
)
388 return wxGIF_INVFORMAT
;
391 stack
[pos
] = code
; /* push last code into the stack */
392 abcabca
= code
; /* save for special case */
394 /* make new entry in alphabet (only if NOT just cleared) */
397 // Normally, after the alphabet is full and can't grow any
398 // further (ab_free == 4096), encoder should (must?) emit CLEAR
399 // to reset it. This checks whether we really got it, otherwise
400 // the GIF is damaged.
401 if (ab_free
> ab_max
)
406 return wxGIF_INVFORMAT
;
409 // This assert seems unnecessary since the condition above
410 // eliminates the only case in which it went false. But I really
411 // don't like being forced to ask "Who in .text could have
412 // written there?!" And I wouldn't have been forced to ask if
413 // this line had already been here.
414 wxASSERT(ab_free
< allocSize
);
416 ab_prefix
[ab_free
] = lastcode
;
417 ab_tail
[ab_free
] = code
;
420 if ((ab_free
> ab_max
) && (ab_bits
< 12))
423 ab_max
= (1 << ab_bits
) - 1;
427 /* dump stack data to the image buffer */
430 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
439 /* support for interlaced images */
442 case 1: y
+= 8; break;
443 case 2: y
+= 8; break;
444 case 3: y
+= 4; break;
445 case 4: y
+= 2; break;
448 /* loop until a valid y coordinate has been
449 found, Or if the maximum number of passes has
450 been reached, exit the loop, and stop image
451 decoding (At this point the image is successfully
453 If we don't loop, but merely set y to some other
454 value, that new value might still be invalid depending
455 on the height of the image. This would cause out of
458 while (y
>= (img
->h
))
462 case 2: y
= 4; break;
463 case 3: y
= 2; break;
464 case 4: y
= 1; break;
468 It's possible we arrive here. For example this
469 happens when the image is interlaced, and the
470 height is 1. Looking at the above cases, the
471 lowest possible y is 1. While the only valid
472 one would be 0 for an image of height 1. So
473 'eventually' the loop will arrive here.
474 This case makes sure this while loop is
475 exited, as well as the 2 other ones.
478 // Set y to a valid coordinate so the local
479 // while loop will be exited. (y = 0 always
480 // is >= img->h since if img->h == 0 the
481 // image is never decoded)
484 // This will exit the other outer while loop
487 // This will halt image decoding.
499 Normally image decoding is finished when an End of Information code is
500 encountered (code == ab_fin) however some broken encoders write wrong
501 "block byte counts" (The first byte value after the "code size" byte),
502 being one value too high. It might very well be possible other variants
503 of this problem occur as well. The only sensible solution seems to
504 be to check for clipping.
505 Example of wrong encoding:
506 (1 * 1 B/W image, raster data stream follows in hex bytes)
508 02 << B/W images have a code size of 2
509 02 << Block byte count
511 00 << Zero byte count (terminates data stream)
513 Because the block byte count is 2, the zero byte count is used in the
514 decoding process, and decoding is continued after this byte. (While it
515 should signal an end of image)
521 01 << When decoded this correctly includes the End of Information code
529 (The 44 doesn't include an End of Information code, but at least the
530 decoder correctly skips to 00 now after decoding, and signals this
531 as an End of Information itself)
545 while (code
!= ab_fin
);
547 delete [] ab_prefix
;
556 // Returns true if the file looks like a valid GIF, false otherwise.
558 bool wxGIFDecoder::CanRead(wxInputStream
&stream
) const
560 unsigned char buf
[3];
562 if ( !stream
.Read(buf
, WXSIZEOF(buf
)) )
565 stream
.SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
);
567 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
572 // Reads and decodes one or more GIF images, depending on whether
573 // animated GIF support is enabled. Can read GIFs with any bit
574 // size (color depth), but the output images are always expanded
575 // to 8 bits per pixel. Also, the image palettes always contain
576 // 256 colors, although some of them may be unused. Returns wxGIF_OK
577 // (== 0) on success, or an error code if something fails (see
578 // header file for details)
580 wxGIFErrorCode
wxGIFDecoder::LoadGIF(wxInputStream
& stream
)
582 unsigned int global_ncolors
= 0;
583 int bits
, interl
, transparent
, i
;
584 wxAnimationDisposal disposal
;
587 unsigned char type
= 0;
588 unsigned char pal
[768];
589 unsigned char buf
[16];
592 /* check GIF signature */
593 if (!CanRead(stream
))
594 return wxGIF_INVFORMAT
;
596 /* check for animated GIF support (ver. >= 89a) */
598 static const size_t headerSize
= (3 + 3);
599 stream
.Read(buf
, headerSize
);
600 if (stream
.LastRead() != headerSize
)
602 return wxGIF_INVFORMAT
;
605 if (memcmp(buf
+ 3, "89a", 3) < 0)
610 /* read logical screen descriptor block (LSDB) */
611 static const size_t lsdbSize
= (2 + 2 + 1 + 1 + 1);
612 stream
.Read(buf
, lsdbSize
);
613 if (stream
.LastRead() != lsdbSize
)
615 return wxGIF_INVFORMAT
;
618 m_szAnimation
.SetWidth( buf
[0] + 256 * buf
[1] );
619 m_szAnimation
.SetHeight( buf
[2] + 256 * buf
[3] );
621 if ((m_szAnimation
.GetWidth() == 0) || (m_szAnimation
.GetHeight() == 0))
623 return wxGIF_INVFORMAT
;
626 /* load global color map if available */
627 if ((buf
[4] & 0x80) == 0x80)
629 int backgroundColIndex
= buf
[5];
631 global_ncolors
= 2 << (buf
[4] & 0x07);
632 size_t numBytes
= 3 * global_ncolors
;
633 stream
.Read(pal
, numBytes
);
634 if (stream
.LastRead() != numBytes
)
636 return wxGIF_INVFORMAT
;
639 m_background
.Set(pal
[backgroundColIndex
*3 + 0],
640 pal
[backgroundColIndex
*3 + 1],
641 pal
[backgroundColIndex
*3 + 2]);
644 /* transparent colour, disposal method and delay default to unused */
646 disposal
= wxANIM_UNSPECIFIED
;
652 type
= (unsigned char)stream
.GetC();
655 If the end of file has been reached (or an error) and a ";"
656 (0x3B) hasn't been encountered yet, exit the loop. (Without this
657 check the while loop would loop endlessly.) Later on, in the next while
658 loop, the file will be treated as being truncated (But still
659 be decoded as far as possible). returning wxGIF_TRUNCATED is not
660 possible here since some init code is done after this loop.
662 if (stream
.Eof())// || !stream.IsOk())
665 type is set to some bogus value, so there's no
666 need to continue evaluating it.
668 break; // Alternative : "return wxGIF_INVFORMAT;"
677 /* extension block? */
680 if (((unsigned char)stream
.GetC()) == 0xF9)
681 /* graphics control extension, parse it */
683 static const size_t gceSize
= 6;
684 stream
.Read(buf
, gceSize
);
685 if (stream
.LastRead() != gceSize
)
688 return wxGIF_INVFORMAT
;
691 /* read delay and convert from 1/100 of a second to ms */
692 delay
= 10 * (buf
[2] + 256 * buf
[3]);
694 /* read transparent colour index, if used */
696 transparent
= buf
[4];
698 /* read disposal method */
699 disposal
= (wxAnimationDisposal
)(((buf
[1] & 0x1C) >> 2) - 1);
702 /* other extension, skip */
704 while ((i
= (unsigned char)stream
.GetC()) != 0)
706 stream
.SeekI(i
, wxFromCurrent
);
716 /* image descriptor block? */
719 /* allocate memory for IMAGEN struct */
720 GIFImage
*pimg
= new GIFImage();
728 /* fill in the data */
729 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
730 stream
.Read(buf
, idbSize
);
731 if (stream
.LastRead() != idbSize
)
734 return wxGIF_INVFORMAT
;
737 pimg
->left
= buf
[0] + 256 * buf
[1];
738 pimg
->top
= buf
[2] + 256 * buf
[3];
740 pimg->left = buf[4] + 256 * buf[5];
741 pimg->top = buf[4] + 256 * buf[5];
743 pimg
->w
= buf
[4] + 256 * buf
[5];
744 pimg
->h
= buf
[6] + 256 * buf
[7];
746 if ((pimg
->w
== 0) || (pimg
->w
> (unsigned int)m_szAnimation
.GetWidth()) ||
747 (pimg
->h
== 0) || (pimg
->h
> (unsigned int)m_szAnimation
.GetHeight()))
750 return wxGIF_INVFORMAT
;
753 interl
= ((buf
[8] & 0x40)? 1 : 0);
754 size
= pimg
->w
* pimg
->h
;
756 pimg
->transparent
= transparent
;
757 pimg
->disposal
= disposal
;
760 /* allocate memory for image and palette */
761 pimg
->p
= (unsigned char *) malloc((size_t)size
);
762 pimg
->pal
= (unsigned char *) malloc(768);
764 if ((!pimg
->p
) || (!pimg
->pal
))
770 /* load local color map if available, else use global map */
771 if ((buf
[8] & 0x80) == 0x80)
773 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
774 size_t numBytes
= 3 * local_ncolors
;
775 stream
.Read(pimg
->pal
, numBytes
);
776 pimg
->ncolours
= local_ncolors
;
777 if (stream
.LastRead() != numBytes
)
780 return wxGIF_INVFORMAT
;
785 memcpy(pimg
->pal
, pal
, 768);
786 pimg
->ncolours
= global_ncolors
;
789 /* get initial code size from first byte in raster data */
790 bits
= (unsigned char)stream
.GetC();
794 return wxGIF_INVFORMAT
;
798 wxGIFErrorCode result
= dgif(stream
, pimg
, interl
, bits
);
799 if (result
!= wxGIF_OK
)
805 /* add the image to our frame array */
806 m_frames
.Add((void*)pimg
);
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 stream
.SeekI(i
, wxFromCurrent
);
840 else if (type
== 0x2C)
842 /* image descriptor block */
843 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
844 stream
.Read(buf
, idbSize
);
845 if (stream
.LastRead() != idbSize
)
848 return wxGIF_INVFORMAT
;
851 /* local color map */
852 if ((buf
[8] & 0x80) == 0x80)
854 unsigned int local_ncolors
= 2 << (buf
[8] & 0x07);
855 wxFileOffset pos
= stream
.TellI();
856 wxFileOffset numBytes
= 3 * local_ncolors
;
857 stream
.SeekI(numBytes
, wxFromCurrent
);
858 if (stream
.TellI() != (pos
+ numBytes
))
861 return wxGIF_INVFORMAT
;
865 /* initial code size */
866 (void) stream
.GetC();
869 while ((i
= (unsigned char)stream
.GetC()) != 0)
871 stream
.SeekI(i
, wxFromCurrent
);
874 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
876 /* images are OK, but couldn't read to the end of the stream */
877 return wxGIF_TRUNCATED
;
884 #endif // wxUSE_STREAMS && wxUSE_GIF