]>
git.saurik.com Git - wxWidgets.git/blob - src/common/gifdecod.cpp
1 /////////////////////////////////////////////////////////////////////////////
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"
20 # include "wx/palette.h"
23 #if wxUSE_STREAMS && wxUSE_GIF
27 #include "wx/gifdecod.h"
30 //---------------------------------------------------------------------------
31 // GIFImage constructor
32 //---------------------------------------------------------------------------
42 p
= (unsigned char *) NULL
;
43 pal
= (unsigned char *) NULL
;
44 next
= (GIFImage
*) NULL
;
45 prev
= (GIFImage
*) NULL
;
48 //---------------------------------------------------------------------------
49 // wxGIFDecoder constructor and destructor
50 //---------------------------------------------------------------------------
52 wxGIFDecoder::wxGIFDecoder(wxInputStream
*s
, bool anim
)
68 wxGIFDecoder::~wxGIFDecoder()
73 void wxGIFDecoder::Destroy()
75 GIFImage
*pimg
, *paux
;
96 //---------------------------------------------------------------------------
97 // Convert this image to a wxImage object
98 //---------------------------------------------------------------------------
100 // This function was designed by Vaclav Slavik
102 bool wxGIFDecoder::ConvertToImage(wxImage
*image
) const
104 unsigned char *src
, *dst
, *pal
;
108 /* just in case... */
111 /* create the image */
112 image
->Create(GetWidth(), GetHeight());
119 dst
= image
->GetData();
120 transparent
= GetTransparentColour();
122 /* set transparent colour mask */
123 if (transparent
!= -1)
125 for (i
= 0; i
< 256; i
++)
127 if ((pal
[3 * i
+ 0] == 255) &&
128 (pal
[3 * i
+ 1] == 0) &&
129 (pal
[3 * i
+ 2] == 255))
131 pal
[3 * i
+ 2] = 254;
135 pal
[3 * transparent
+ 0] = 255,
136 pal
[3 * transparent
+ 1] = 0,
137 pal
[3 * transparent
+ 2] = 255;
139 image
->SetMaskColour(255, 0, 255);
142 image
->SetMask(false);
147 unsigned char r
[256];
148 unsigned char g
[256];
149 unsigned char b
[256];
151 for (i
= 0; i
< 256; i
++)
158 image
->SetPalette(wxPalette(256, r
, g
, b
));
160 #endif // wxUSE_PALETTE
162 /* copy image data */
163 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
165 *(dst
++) = pal
[3 * (*src
) + 0];
166 *(dst
++) = pal
[3 * (*src
) + 1];
167 *(dst
++) = pal
[3 * (*src
) + 2];
174 //---------------------------------------------------------------------------
176 //---------------------------------------------------------------------------
178 // Get data for current frame
180 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
181 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
182 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
183 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
184 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
185 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
186 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
187 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
188 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
189 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
193 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
194 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
195 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
196 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
197 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
200 //---------------------------------------------------------------------------
201 // Functions to move through the animation
202 //---------------------------------------------------------------------------
204 bool wxGIFDecoder::GoFirstFrame()
214 bool wxGIFDecoder::GoLastFrame()
224 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
229 if ((m_image
< m_nimages
) || (cyclic
))
231 m_pimage
= m_pimage
->next
;
246 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
251 if ((m_image
> 1) || (cyclic
))
253 m_pimage
= m_pimage
->prev
;
268 bool wxGIFDecoder::GoFrame(int which
)
273 if ((which
>= 1) && (which
<= m_nimages
))
278 while (m_image
< which
)
281 m_pimage
= m_pimage
->next
;
291 //---------------------------------------------------------------------------
292 // GIF reading and decoding
293 //---------------------------------------------------------------------------
296 // Reads the next code from the file stream, with size 'bits'
298 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
300 unsigned int mask
; /* bit mask */
301 unsigned int code
; /* code (result) */
304 /* get remaining bits from last byte read */
305 mask
= (1 << bits
) - 1;
306 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
308 /* keep reading new bytes while needed */
309 while (bits
> m_restbits
)
311 /* if no bytes left in this block, read the next block */
314 m_restbyte
= (unsigned char)m_f
->GetC();
316 /* Some encoders are a bit broken: instead of issuing
317 * an end-of-image symbol (ab_fin) they come up with
318 * a zero-length subblock!! We catch this here so
319 * that the decoder sees an ab_fin code.
328 m_f
->Read((void *) m_buffer
, m_restbyte
);
329 if (m_f
->LastRead() != m_restbyte
)
337 /* read next byte and isolate the bits we need */
338 m_lastbyte
= (unsigned char) (*m_bufp
++);
339 mask
= (1 << (bits
- m_restbits
)) - 1;
340 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
343 /* adjust total number of bits extracted from the buffer */
344 m_restbits
= m_restbits
+ 8;
347 /* find number of bits remaining for next code */
348 m_restbits
= (m_restbits
- bits
);
355 // GIF decoding function. The initial code size (aka root size)
356 // is 'bits'. Supports interlaced images (interl == 1).
357 // Returns wxGIF_OK (== 0) on success, or an error code if something
358 // fails (see header file for details)
359 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
361 static const int allocSize
= 4096 + 1;
362 int *ab_prefix
= new int[allocSize
]; /* alphabet (prefixes) */
363 if (ab_prefix
== NULL
)
368 int *ab_tail
= new int[allocSize
]; /* alphabet (tails) */
375 int *stack
= new int[allocSize
]; /* decompression stack */
383 int ab_clr
; /* clear code */
384 int ab_fin
; /* end of info code */
385 int ab_bits
; /* actual symbol width, in bits */
386 int ab_free
; /* first free position in alphabet */
387 int ab_max
; /* last possible character in alphabet */
388 int pass
; /* pass number in interlaced images */
389 int pos
; /* index into decompresion stack */
390 unsigned int x
, y
; /* position in image buffer */
392 int code
, readcode
, lastcode
, abcabca
;
394 /* these won't change */
395 ab_clr
= (1 << bits
);
396 ab_fin
= (1 << bits
) + 1;
398 /* these will change through the decompression proccess */
400 ab_free
= (1 << bits
) + 2;
401 ab_max
= (1 << ab_bits
) - 1;
407 /* reset decoder vars */
415 readcode
= code
= getcode(ab_bits
, ab_fin
);
418 if (code
== ab_fin
) break;
420 /* reset alphabet? */
423 /* reset main variables */
425 ab_free
= (1 << bits
) + 2;
426 ab_max
= (1 << ab_bits
) - 1;
430 /* skip to next code */
434 /* unknown code: special case (like in ABCABCA) */
437 code
= lastcode
; /* take last string */
438 stack
[pos
++] = abcabca
; /* add first character */
441 /* build the string for this code in the stack */
442 while (code
> ab_clr
)
444 stack
[pos
++] = ab_tail
[code
];
445 code
= ab_prefix
[code
];
447 // Don't overflow. This shouldn't happen with normal
448 // GIF files, the allocSize of 4096+1 is enough. This
449 // will only happen with badly formed GIFs.
450 if (pos
>= allocSize
)
455 return wxGIF_INVFORMAT
;
459 if (pos
>= allocSize
)
464 return wxGIF_INVFORMAT
;
467 stack
[pos
] = code
; /* push last code into the stack */
468 abcabca
= code
; /* save for special case */
470 /* make new entry in alphabet (only if NOT just cleared) */
473 ab_prefix
[ab_free
] = lastcode
;
474 ab_tail
[ab_free
] = code
;
477 if ((ab_free
> ab_max
) && (ab_bits
< 12))
480 ab_max
= (1 << ab_bits
) - 1;
484 /* dump stack data to the image buffer */
487 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
496 /* support for interlaced images */
499 case 1: y
+= 8; break;
500 case 2: y
+= 8; break;
501 case 3: y
+= 4; break;
502 case 4: y
+= 2; break;
505 /* loop until a valid y coordinate has been
506 found, Or if the maximum number of passes has
507 been reached, exit the loop, and stop image
508 decoding (At this point the image is successfully
510 If we don't loop, but merely set y to some other
511 value, that new value might still be invalid depending
512 on the height of the image. This would cause out of
515 while (y
>= (img
->h
))
519 case 2: y
= 4; break;
520 case 3: y
= 2; break;
521 case 4: y
= 1; break;
525 It's possible we arrive here. For example this
526 happens when the image is interlaced, and the
527 height is 1. Looking at the above cases, the
528 lowest possible y is 1. While the only valid
529 one would be 0 for an image of height 1. So
530 'eventually' the loop will arrive here.
531 This case makes sure this while loop is
532 exited, as well as the 2 other ones.
535 // Set y to a valid coordinate so the local
536 // while loop will be exited. (y = 0 always
537 // is >= img->h since if img->h == 0 the
538 // image is never decoded)
541 // This will exit the other outer while loop
544 // This will halt image decoding.
556 Normally image decoding is finished when an End of Information code is
557 encountered (code == ab_fin) however some broken encoders write wrong
558 "block byte counts" (The first byte value after the "code size" byte),
559 being one value too high. It might very well be possible other variants
560 of this problem occur as well. The only sensible solution seems to
561 be to check for clipping.
562 Example of wrong encoding:
563 (1 * 1 B/W image, raster data stream follows in hex bytes)
565 02 << B/W images have a code size of 2
566 02 << Block byte count
568 00 << Zero byte count (terminates data stream)
570 Because the block byte count is 2, the zero byte count is used in the
571 decoding process, and decoding is continued after this byte. (While it
572 should signal an end of image)
578 01 << When decoded this correctly includes the End of Information code
586 (The 44 doesn't include an End of Information code, but at least the
587 decoder correctly skips to 00 now after decoding, and signals this
588 as an End of Information itself)
602 while (code
!= ab_fin
);
604 delete [] ab_prefix
;
613 // Returns true if the file looks like a valid GIF, false otherwise.
615 bool wxGIFDecoder::CanRead()
617 unsigned char buf
[3];
619 if ( !m_f
->Read(buf
, WXSIZEOF(buf
)) )
622 m_f
->SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
);
624 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
629 // Reads and decodes one or more GIF images, depending on whether
630 // animated GIF support is enabled. Can read GIFs with any bit
631 // size (color depth), but the output images are always expanded
632 // to 8 bits per pixel. Also, the image palettes always contain
633 // 256 colors, although some of them may be unused. Returns wxGIF_OK
634 // (== 0) on success, or an error code if something fails (see
635 // header file for details)
637 int wxGIFDecoder::ReadGIF()
639 unsigned int ncolors
;
640 int bits
, interl
, transparent
, disposal
, i
;
643 unsigned char type
= 0;
644 unsigned char pal
[768];
645 unsigned char buf
[16];
647 GIFImage
*pimg
, *pprev
;
649 /* check GIF signature */
651 return wxGIF_INVFORMAT
;
653 /* check for animated GIF support (ver. >= 89a) */
655 static const size_t headerSize
= (3 + 3);
656 m_f
->Read(buf
, headerSize
);
657 if (m_f
->LastRead() != headerSize
)
659 return wxGIF_INVFORMAT
;
662 if (memcmp(buf
+ 3, "89a", 3) < 0)
667 /* read logical screen descriptor block (LSDB) */
668 static const size_t lsdbSize
= (2 + 2 + 1 + 1 + 1);
669 m_f
->Read(buf
, lsdbSize
);
670 if (m_f
->LastRead() != lsdbSize
)
672 return wxGIF_INVFORMAT
;
675 m_screenw
= buf
[0] + 256 * buf
[1];
676 m_screenh
= buf
[2] + 256 * buf
[3];
678 if ((m_screenw
== 0) || (m_screenh
== 0))
680 return wxGIF_INVFORMAT
;
683 /* load global color map if available */
684 if ((buf
[4] & 0x80) == 0x80)
686 m_background
= buf
[5];
688 ncolors
= 2 << (buf
[4] & 0x07);
689 size_t numBytes
= 3 * ncolors
;
690 m_f
->Read(pal
, numBytes
);
691 if (m_f
->LastRead() != numBytes
)
693 return wxGIF_INVFORMAT
;
697 /* transparent colour, disposal method and delay default to unused */
711 type
= (unsigned char)m_f
->GetC();
714 If the end of file has been reached (or an error) and a ";"
715 (0x3B) hasn't been encountered yet, exit the loop. (Without this
716 check the while loop would loop endlessly.) Later on, in the next while
717 loop, the file will be treated as being truncated (But still
718 be decoded as far as possible). returning wxGIF_TRUNCATED is not
719 possible here since some init code is done after this loop.
721 if (m_f
->Eof())// || !m_f->IsOk())
724 type is set to some bogus value, so there's no
725 need to continue evaluating it.
727 break; // Alternative : "return wxGIF_INVFORMAT;"
736 /* extension block? */
739 if (((unsigned char)m_f
->GetC()) == 0xF9)
740 /* graphics control extension, parse it */
742 static const size_t gceSize
= 6;
743 m_f
->Read(buf
, gceSize
);
744 if (m_f
->LastRead() != gceSize
)
747 return wxGIF_INVFORMAT
;
750 /* read delay and convert from 1/100 of a second to ms */
751 delay
= 10 * (buf
[2] + 256 * buf
[3]);
753 /* read transparent colour index, if used */
755 transparent
= buf
[4];
757 /* read disposal method */
758 disposal
= ((buf
[1] & 0x1C) >> 2) - 1;
761 /* other extension, skip */
763 while ((i
= (unsigned char)m_f
->GetC()) != 0)
765 m_f
->SeekI(i
, wxFromCurrent
);
775 /* image descriptor block? */
778 /* allocate memory for IMAGEN struct */
779 pimg
= (*ppimg
) = new GIFImage();
787 /* fill in the data */
788 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
789 m_f
->Read(buf
, idbSize
);
790 if (m_f
->LastRead() != idbSize
)
793 return wxGIF_INVFORMAT
;
796 pimg
->left
= buf
[0] + 256 * buf
[1];
797 pimg
->top
= buf
[2] + 256 * buf
[3];
799 pimg->left = buf[4] + 256 * buf[5];
800 pimg->top = buf[4] + 256 * buf[5];
802 pimg
->w
= buf
[4] + 256 * buf
[5];
803 pimg
->h
= buf
[6] + 256 * buf
[7];
805 if ((pimg
->w
== 0) || (pimg
->w
> m_screenw
) || (pimg
->h
== 0) || (pimg
->h
> m_screenh
))
808 return wxGIF_INVFORMAT
;
811 interl
= ((buf
[8] & 0x40)? 1 : 0);
812 size
= pimg
->w
* pimg
->h
;
814 pimg
->transparent
= transparent
;
815 pimg
->disposal
= disposal
;
822 /* allocate memory for image and palette */
823 pimg
->p
= (unsigned char *) malloc((size_t)size
);
824 pimg
->pal
= (unsigned char *) malloc(768);
826 if ((!pimg
->p
) || (!pimg
->pal
))
832 /* load local color map if available, else use global map */
833 if ((buf
[8] & 0x80) == 0x80)
835 ncolors
= 2 << (buf
[8] & 0x07);
836 size_t numBytes
= 3 * ncolors
;
837 m_f
->Read(pimg
->pal
, numBytes
);
838 if (m_f
->LastRead() != numBytes
)
841 return wxGIF_INVFORMAT
;
846 memcpy(pimg
->pal
, pal
, 768);
849 /* get initial code size from first byte in raster data */
850 bits
= (unsigned char)m_f
->GetC();
854 return wxGIF_INVFORMAT
;
858 int result
= dgif(pimg
, interl
, bits
);
859 if (result
!= wxGIF_OK
)
866 /* if this is not an animated GIF, exit after first image */
875 return wxGIF_INVFORMAT
;
878 /* setup image pointers */
883 /* try to read to the end of the stream */
887 return wxGIF_TRUNCATED
;
889 type
= (unsigned char)m_f
->GetC();
897 while ((i
= (unsigned char)m_f
->GetC()) != 0)
899 m_f
->SeekI(i
, wxFromCurrent
);
902 else if (type
== 0x2C)
904 /* image descriptor block */
905 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
906 m_f
->Read(buf
, idbSize
);
907 if (m_f
->LastRead() != idbSize
)
910 return wxGIF_INVFORMAT
;
913 /* local color map */
914 if ((buf
[8] & 0x80) == 0x80)
916 ncolors
= 2 << (buf
[8] & 0x07);
917 wxFileOffset pos
= m_f
->TellI();
918 wxFileOffset numBytes
= 3 * ncolors
;
919 m_f
->SeekI(numBytes
, wxFromCurrent
);
920 if (m_f
->TellI() != (pos
+ numBytes
))
923 return wxGIF_INVFORMAT
;
927 /* initial code size */
931 while ((i
= (unsigned char)m_f
->GetC()) != 0)
933 m_f
->SeekI(i
, wxFromCurrent
);
936 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
938 /* images are OK, but couldn't read to the end of the stream */
939 return wxGIF_TRUNCATED
;
946 #endif // wxUSE_STREAMS && wxUSE_GIF