]>
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12 #pragma implementation "gifdecod.h"
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
24 # include "wx/palette.h"
27 #if wxUSE_STREAMS && wxUSE_GIF
31 #include "wx/gifdecod.h"
34 //---------------------------------------------------------------------------
35 // GIFImage constructor
36 //---------------------------------------------------------------------------
46 p
= (unsigned char *) NULL
;
47 pal
= (unsigned char *) NULL
;
48 next
= (GIFImage
*) NULL
;
49 prev
= (GIFImage
*) NULL
;
52 //---------------------------------------------------------------------------
53 // wxGIFDecoder constructor and destructor
54 //---------------------------------------------------------------------------
56 wxGIFDecoder::wxGIFDecoder(wxInputStream
*s
, bool anim
)
72 wxGIFDecoder::~wxGIFDecoder()
77 void wxGIFDecoder::Destroy()
79 GIFImage
*pimg
, *paux
;
100 //---------------------------------------------------------------------------
101 // Convert this image to a wxImage object
102 //---------------------------------------------------------------------------
104 // This function was designed by Vaclav Slavik
106 bool wxGIFDecoder::ConvertToImage(wxImage
*image
) const
108 unsigned char *src
, *dst
, *pal
;
112 /* just in case... */
115 /* create the image */
116 image
->Create(GetWidth(), GetHeight());
123 dst
= image
->GetData();
124 transparent
= GetTransparentColour();
126 /* set transparent colour mask */
127 if (transparent
!= -1)
129 for (i
= 0; i
< 256; i
++)
131 if ((pal
[3 * i
+ 0] == 255) &&
132 (pal
[3 * i
+ 1] == 0) &&
133 (pal
[3 * i
+ 2] == 255))
135 pal
[3 * i
+ 2] = 254;
139 pal
[3 * transparent
+ 0] = 255,
140 pal
[3 * transparent
+ 1] = 0,
141 pal
[3 * transparent
+ 2] = 255;
143 image
->SetMaskColour(255, 0, 255);
146 image
->SetMask(false);
151 unsigned char r
[256];
152 unsigned char g
[256];
153 unsigned char b
[256];
155 for (i
= 0; i
< 256; i
++)
162 image
->SetPalette(wxPalette(256, r
, g
, b
));
164 #endif // wxUSE_PALETTE
166 /* copy image data */
167 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
169 *(dst
++) = pal
[3 * (*src
) + 0];
170 *(dst
++) = pal
[3 * (*src
) + 1];
171 *(dst
++) = pal
[3 * (*src
) + 2];
178 //---------------------------------------------------------------------------
180 //---------------------------------------------------------------------------
182 // Get data for current frame
184 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
185 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
186 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
187 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
188 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
189 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
190 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
191 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
192 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
193 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
197 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
198 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
199 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
200 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
201 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
204 //---------------------------------------------------------------------------
205 // Functions to move through the animation
206 //---------------------------------------------------------------------------
208 bool wxGIFDecoder::GoFirstFrame()
218 bool wxGIFDecoder::GoLastFrame()
228 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
233 if ((m_image
< m_nimages
) || (cyclic
))
235 m_pimage
= m_pimage
->next
;
250 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
255 if ((m_image
> 1) || (cyclic
))
257 m_pimage
= m_pimage
->prev
;
272 bool wxGIFDecoder::GoFrame(int which
)
279 if ((which
>= 1) && (which
<= m_nimages
))
283 for (i
= 0; i
< which
; i
++)
284 m_pimage
= m_pimage
->next
;
293 //---------------------------------------------------------------------------
294 // GIF reading and decoding
295 //---------------------------------------------------------------------------
298 // Reads the next code from the file stream, with size 'bits'
300 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
302 unsigned int mask
; /* bit mask */
303 unsigned int code
; /* code (result) */
306 /* get remaining bits from last byte read */
307 mask
= (1 << bits
) - 1;
308 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
310 /* keep reading new bytes while needed */
311 while (bits
> m_restbits
)
313 /* if no bytes left in this block, read the next block */
316 m_restbyte
= (unsigned char)m_f
->GetC();
318 /* Some encoders are a bit broken: instead of issuing
319 * an end-of-image symbol (ab_fin) they come up with
320 * a zero-length subblock!! We catch this here so
321 * that the decoder sees an ab_fin code.
330 m_f
->Read((void *) m_buffer
, m_restbyte
);
331 if (m_f
->LastRead() != m_restbyte
)
339 /* read next byte and isolate the bits we need */
340 m_lastbyte
= (unsigned char) (*m_bufp
++);
341 mask
= (1 << (bits
- m_restbits
)) - 1;
342 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
345 /* adjust total number of bits extracted from the buffer */
346 m_restbits
= m_restbits
+ 8;
349 /* find number of bits remaining for next code */
350 m_restbits
= (m_restbits
- bits
);
357 // GIF decoding function. The initial code size (aka root size)
358 // is 'bits'. Supports interlaced images (interl == 1).
359 // Returns wxGIF_OK (== 0) on success, or an error code if something
360 // fails (see header file for details)
361 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
363 static const int allocSize
= 4096 + 1;
364 int *ab_prefix
= new int[allocSize
]; /* alphabet (prefixes) */
365 if (ab_prefix
== NULL
)
370 int *ab_tail
= new int[allocSize
]; /* alphabet (tails) */
377 int *stack
= new int[allocSize
]; /* decompression stack */
385 int ab_clr
; /* clear code */
386 int ab_fin
; /* end of info code */
387 int ab_bits
; /* actual symbol width, in bits */
388 int ab_free
; /* first free position in alphabet */
389 int ab_max
; /* last possible character in alphabet */
390 int pass
; /* pass number in interlaced images */
391 int pos
; /* index into decompresion stack */
392 unsigned int x
, y
; /* position in image buffer */
394 int code
, readcode
, lastcode
, abcabca
;
396 /* these won't change */
397 ab_clr
= (1 << bits
);
398 ab_fin
= (1 << bits
) + 1;
400 /* these will change through the decompression proccess */
402 ab_free
= (1 << bits
) + 2;
403 ab_max
= (1 << ab_bits
) - 1;
409 /* reset decoder vars */
417 readcode
= code
= getcode(ab_bits
, ab_fin
);
420 if (code
== ab_fin
) break;
422 /* reset alphabet? */
425 /* reset main variables */
427 ab_free
= (1 << bits
) + 2;
428 ab_max
= (1 << ab_bits
) - 1;
432 /* skip to next code */
436 /* unknown code: special case (like in ABCABCA) */
439 code
= lastcode
; /* take last string */
440 stack
[pos
++] = abcabca
; /* add first character */
443 /* build the string for this code in the stack */
444 while (code
> ab_clr
)
446 stack
[pos
++] = ab_tail
[code
];
447 code
= ab_prefix
[code
];
449 // Don't overflow. This shouldn't happen with normal
450 // GIF files, the allocSize of 4096+1 is enough. This
451 // will only happen with badly formed GIFs.
452 if (pos
>= allocSize
)
457 return wxGIF_INVFORMAT
;
461 if (pos
>= allocSize
)
466 return wxGIF_INVFORMAT
;
469 stack
[pos
] = code
; /* push last code into the stack */
470 abcabca
= code
; /* save for special case */
472 /* make new entry in alphabet (only if NOT just cleared) */
475 ab_prefix
[ab_free
] = lastcode
;
476 ab_tail
[ab_free
] = code
;
479 if ((ab_free
> ab_max
) && (ab_bits
< 12))
482 ab_max
= (1 << ab_bits
) - 1;
486 /* dump stack data to the image buffer */
489 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
498 /* support for interlaced images */
501 case 1: y
+= 8; break;
502 case 2: y
+= 8; break;
503 case 3: y
+= 4; break;
504 case 4: y
+= 2; break;
507 /* loop until a valid y coordinate has been
508 found, Or if the maximum number of passes has
509 been reached, exit the loop, and stop image
510 decoding (At this point the image is succesfully
512 If we don't loop, but merely set y to some other
513 value, that new value might still be invalid depending
514 on the height of the image. This would cause out of
517 while (y
>= (img
->h
))
521 case 2: y
= 4; break;
522 case 3: y
= 2; break;
523 case 4: y
= 1; break;
527 It's possible we arrive here. For example this
528 happens when the image is interlaced, and the
529 height is 1. Looking at the above cases, the
530 lowest possible y is 1. While the only valid
531 one would be 0 for an image of height 1. So
532 'eventually' the loop will arrive here.
533 This case makes sure this while loop is
534 exited, as well as the 2 other ones.
537 // Set y to a valid coordinate so the local
538 // while loop will be exited. (y = 0 always
539 // is >= img->h since if img->h == 0 the
540 // image is never decoded)
543 // This will exit the other outer while loop
546 // This will halt image decoding.
558 Normally image decoding is finished when an End of Information code is
559 encountered (code == ab_fin) however some broken encoders write wrong
560 "block byte counts" (The first byte value after the "code size" byte),
561 being one value too high. It might very well be possible other variants
562 of this problem occur as well. The only sensible solution seems to
563 be to check for clipping.
564 Example of wrong encoding:
565 (1 * 1 B/W image, raster data stream follows in hex bytes)
567 02 << B/W images have a code size of 2
568 02 << Block byte count
570 00 << Zero byte count (terminates data stream)
572 Because the block byte count is 2, the zero byte count is used in the
573 decoding process, and decoding is continued after this byte. (While it
574 should signal an end of image)
580 01 << When decoded this correctly includes the End of Information code
588 (The 44 doesn't include an End of Information code, but at least the
589 decoder correctly skips to 00 now after decoding, and signals this
590 as an End of Information itself)
604 while (code
!= ab_fin
);
606 delete [] ab_prefix
;
615 // Returns true if the file looks like a valid GIF, false otherwise.
617 bool wxGIFDecoder::CanRead()
619 unsigned char buf
[3];
621 if ( !m_f
->Read(buf
, WXSIZEOF(buf
)) )
624 m_f
->SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
);
626 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
631 // Reads and decodes one or more GIF images, depending on whether
632 // animated GIF support is enabled. Can read GIFs with any bit
633 // size (color depth), but the output images are always expanded
634 // to 8 bits per pixel. Also, the image palettes always contain
635 // 256 colors, although some of them may be unused. Returns wxGIF_OK
636 // (== 0) on success, or an error code if something fails (see
637 // header file for details)
639 int wxGIFDecoder::ReadGIF()
641 unsigned int ncolors
;
642 int bits
, interl
, transparent
, disposal
, i
;
645 unsigned char type
= 0;
646 unsigned char pal
[768];
647 unsigned char buf
[16];
649 GIFImage
*pimg
, *pprev
;
651 /* check GIF signature */
653 return wxGIF_INVFORMAT
;
655 /* check for animated GIF support (ver. >= 89a) */
657 static const size_t headerSize
= (3 + 3);
658 m_f
->Read(buf
, headerSize
);
659 if (m_f
->LastRead() != headerSize
)
661 return wxGIF_INVFORMAT
;
664 if (memcmp(buf
+ 3, "89a", 3) < 0)
669 /* read logical screen descriptor block (LSDB) */
670 static const size_t lsdbSize
= (2 + 2 + 1 + 1 + 1);
671 m_f
->Read(buf
, lsdbSize
);
672 if (m_f
->LastRead() != lsdbSize
)
674 return wxGIF_INVFORMAT
;
677 m_screenw
= buf
[0] + 256 * buf
[1];
678 m_screenh
= buf
[2] + 256 * buf
[3];
680 /* load global color map if available */
681 if ((buf
[4] & 0x80) == 0x80)
683 m_background
= buf
[5];
685 ncolors
= 2 << (buf
[4] & 0x07);
686 size_t numBytes
= 3 * ncolors
;
687 m_f
->Read(pal
, numBytes
);
688 if (m_f
->LastRead() != numBytes
)
690 return wxGIF_INVFORMAT
;
694 /* transparent colour, disposal method and delay default to unused */
708 type
= (unsigned char)m_f
->GetC();
711 If the end of file has been reached (or an error) and a ";"
712 (0x3B) hasn't been encountered yet, exit the loop. (Without this
713 check the while loop would loop endlessly.) Later on, in the next while
714 loop, the file will be treated as being truncated (But still
715 be decoded as far as possible). returning wxGIF_TRUNCATED is not
716 possible here since some init code is done after this loop.
718 if (m_f
->Eof())// || !m_f->IsOk())
721 type is set to some bogus value, so there's no
722 need to continue evaluating it.
724 break; // Alternative : "return wxGIF_INVFORMAT;"
733 /* extension block? */
736 if (((unsigned char)m_f
->GetC()) == 0xF9)
737 /* graphics control extension, parse it */
739 static const size_t gceSize
= 6;
740 m_f
->Read(buf
, gceSize
);
741 if (m_f
->LastRead() != gceSize
)
744 return wxGIF_INVFORMAT
;
747 /* read delay and convert from 1/100 of a second to ms */
748 delay
= 10 * (buf
[2] + 256 * buf
[3]);
750 /* read transparent colour index, if used */
752 transparent
= buf
[4];
754 /* read disposal method */
755 disposal
= (buf
[1] & 0x1C) - 1;
758 /* other extension, skip */
760 while ((i
= (unsigned char)m_f
->GetC()) != 0)
762 m_f
->SeekI(i
, wxFromCurrent
);
772 /* image descriptor block? */
775 /* allocate memory for IMAGEN struct */
776 pimg
= (*ppimg
) = new GIFImage();
784 /* fill in the data */
785 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
786 m_f
->Read(buf
, idbSize
);
787 if (m_f
->LastRead() != idbSize
)
790 return wxGIF_INVFORMAT
;
793 pimg
->left
= buf
[0] + 256 * buf
[1];
794 pimg
->top
= buf
[2] + 256 * buf
[3];
796 pimg->left = buf[4] + 256 * buf[5];
797 pimg->top = buf[4] + 256 * buf[5];
799 pimg
->w
= buf
[4] + 256 * buf
[5];
800 pimg
->h
= buf
[6] + 256 * buf
[7];
802 if (pimg
->w
== 0 || pimg
->h
== 0)
805 return wxGIF_INVFORMAT
;
808 interl
= ((buf
[8] & 0x40)? 1 : 0);
809 size
= pimg
->w
* pimg
->h
;
811 pimg
->transparent
= transparent
;
812 pimg
->disposal
= disposal
;
819 /* allocate memory for image and palette */
820 pimg
->p
= (unsigned char *) malloc((size_t)size
);
821 pimg
->pal
= (unsigned char *) malloc(768);
823 if ((!pimg
->p
) || (!pimg
->pal
))
829 /* load local color map if available, else use global map */
830 if ((buf
[8] & 0x80) == 0x80)
832 ncolors
= 2 << (buf
[8] & 0x07);
833 size_t numBytes
= 3 * ncolors
;
834 m_f
->Read(pimg
->pal
, numBytes
);
835 if (m_f
->LastRead() != numBytes
)
838 return wxGIF_INVFORMAT
;
843 memcpy(pimg
->pal
, pal
, 768);
846 /* get initial code size from first byte in raster data */
847 bits
= (unsigned char)m_f
->GetC();
850 int result
= dgif(pimg
, interl
, bits
);
851 if (result
!= wxGIF_OK
)
858 /* if this is not an animated GIF, exit after first image */
867 return wxGIF_INVFORMAT
;
870 /* setup image pointers */
875 /* try to read to the end of the stream */
879 return wxGIF_TRUNCATED
;
881 type
= (unsigned char)m_f
->GetC();
889 while ((i
= (unsigned char)m_f
->GetC()) != 0)
891 m_f
->SeekI(i
, wxFromCurrent
);
894 else if (type
== 0x2C)
896 /* image descriptor block */
897 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
898 m_f
->Read(buf
, idbSize
);
899 if (m_f
->LastRead() != idbSize
)
902 return wxGIF_INVFORMAT
;
905 /* local color map */
906 if ((buf
[8] & 0x80) == 0x80)
908 ncolors
= 2 << (buf
[8] & 0x07);
909 wxFileOffset pos
= m_f
->TellI();
910 wxFileOffset numBytes
= 3 * ncolors
;
911 m_f
->SeekI(numBytes
, wxFromCurrent
);
912 if (m_f
->TellI() != (pos
+ numBytes
))
915 return wxGIF_INVFORMAT
;
919 /* initial code size */
923 while ((i
= (unsigned char)m_f
->GetC()) != 0)
925 m_f
->SeekI(i
, wxFromCurrent
);
928 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
930 /* images are OK, but couldn't read to the end of the stream */
931 return wxGIF_TRUNCATED
;
938 #endif // wxUSE_STREAMS && wxUSE_GIF