]>
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
)
277 if ((which
>= 1) && (which
<= m_nimages
))
282 while (m_image
< which
)
285 m_pimage
= m_pimage
->next
;
295 //---------------------------------------------------------------------------
296 // GIF reading and decoding
297 //---------------------------------------------------------------------------
300 // Reads the next code from the file stream, with size 'bits'
302 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
304 unsigned int mask
; /* bit mask */
305 unsigned int code
; /* code (result) */
308 /* get remaining bits from last byte read */
309 mask
= (1 << bits
) - 1;
310 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
312 /* keep reading new bytes while needed */
313 while (bits
> m_restbits
)
315 /* if no bytes left in this block, read the next block */
318 m_restbyte
= (unsigned char)m_f
->GetC();
320 /* Some encoders are a bit broken: instead of issuing
321 * an end-of-image symbol (ab_fin) they come up with
322 * a zero-length subblock!! We catch this here so
323 * that the decoder sees an ab_fin code.
332 m_f
->Read((void *) m_buffer
, m_restbyte
);
333 if (m_f
->LastRead() != m_restbyte
)
341 /* read next byte and isolate the bits we need */
342 m_lastbyte
= (unsigned char) (*m_bufp
++);
343 mask
= (1 << (bits
- m_restbits
)) - 1;
344 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
347 /* adjust total number of bits extracted from the buffer */
348 m_restbits
= m_restbits
+ 8;
351 /* find number of bits remaining for next code */
352 m_restbits
= (m_restbits
- bits
);
359 // GIF decoding function. The initial code size (aka root size)
360 // is 'bits'. Supports interlaced images (interl == 1).
361 // Returns wxGIF_OK (== 0) on success, or an error code if something
362 // fails (see header file for details)
363 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
365 static const int allocSize
= 4096 + 1;
366 int *ab_prefix
= new int[allocSize
]; /* alphabet (prefixes) */
367 if (ab_prefix
== NULL
)
372 int *ab_tail
= new int[allocSize
]; /* alphabet (tails) */
379 int *stack
= new int[allocSize
]; /* decompression stack */
387 int ab_clr
; /* clear code */
388 int ab_fin
; /* end of info code */
389 int ab_bits
; /* actual symbol width, in bits */
390 int ab_free
; /* first free position in alphabet */
391 int ab_max
; /* last possible character in alphabet */
392 int pass
; /* pass number in interlaced images */
393 int pos
; /* index into decompresion stack */
394 unsigned int x
, y
; /* position in image buffer */
396 int code
, readcode
, lastcode
, abcabca
;
398 /* these won't change */
399 ab_clr
= (1 << bits
);
400 ab_fin
= (1 << bits
) + 1;
402 /* these will change through the decompression proccess */
404 ab_free
= (1 << bits
) + 2;
405 ab_max
= (1 << ab_bits
) - 1;
411 /* reset decoder vars */
419 readcode
= code
= getcode(ab_bits
, ab_fin
);
422 if (code
== ab_fin
) break;
424 /* reset alphabet? */
427 /* reset main variables */
429 ab_free
= (1 << bits
) + 2;
430 ab_max
= (1 << ab_bits
) - 1;
434 /* skip to next code */
438 /* unknown code: special case (like in ABCABCA) */
441 code
= lastcode
; /* take last string */
442 stack
[pos
++] = abcabca
; /* add first character */
445 /* build the string for this code in the stack */
446 while (code
> ab_clr
)
448 stack
[pos
++] = ab_tail
[code
];
449 code
= ab_prefix
[code
];
451 // Don't overflow. This shouldn't happen with normal
452 // GIF files, the allocSize of 4096+1 is enough. This
453 // will only happen with badly formed GIFs.
454 if (pos
>= allocSize
)
459 return wxGIF_INVFORMAT
;
463 if (pos
>= allocSize
)
468 return wxGIF_INVFORMAT
;
471 stack
[pos
] = code
; /* push last code into the stack */
472 abcabca
= code
; /* save for special case */
474 /* make new entry in alphabet (only if NOT just cleared) */
477 ab_prefix
[ab_free
] = lastcode
;
478 ab_tail
[ab_free
] = code
;
481 if ((ab_free
> ab_max
) && (ab_bits
< 12))
484 ab_max
= (1 << ab_bits
) - 1;
488 /* dump stack data to the image buffer */
491 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
500 /* support for interlaced images */
503 case 1: y
+= 8; break;
504 case 2: y
+= 8; break;
505 case 3: y
+= 4; break;
506 case 4: y
+= 2; break;
509 /* loop until a valid y coordinate has been
510 found, Or if the maximum number of passes has
511 been reached, exit the loop, and stop image
512 decoding (At this point the image is successfully
514 If we don't loop, but merely set y to some other
515 value, that new value might still be invalid depending
516 on the height of the image. This would cause out of
519 while (y
>= (img
->h
))
523 case 2: y
= 4; break;
524 case 3: y
= 2; break;
525 case 4: y
= 1; break;
529 It's possible we arrive here. For example this
530 happens when the image is interlaced, and the
531 height is 1. Looking at the above cases, the
532 lowest possible y is 1. While the only valid
533 one would be 0 for an image of height 1. So
534 'eventually' the loop will arrive here.
535 This case makes sure this while loop is
536 exited, as well as the 2 other ones.
539 // Set y to a valid coordinate so the local
540 // while loop will be exited. (y = 0 always
541 // is >= img->h since if img->h == 0 the
542 // image is never decoded)
545 // This will exit the other outer while loop
548 // This will halt image decoding.
560 Normally image decoding is finished when an End of Information code is
561 encountered (code == ab_fin) however some broken encoders write wrong
562 "block byte counts" (The first byte value after the "code size" byte),
563 being one value too high. It might very well be possible other variants
564 of this problem occur as well. The only sensible solution seems to
565 be to check for clipping.
566 Example of wrong encoding:
567 (1 * 1 B/W image, raster data stream follows in hex bytes)
569 02 << B/W images have a code size of 2
570 02 << Block byte count
572 00 << Zero byte count (terminates data stream)
574 Because the block byte count is 2, the zero byte count is used in the
575 decoding process, and decoding is continued after this byte. (While it
576 should signal an end of image)
582 01 << When decoded this correctly includes the End of Information code
590 (The 44 doesn't include an End of Information code, but at least the
591 decoder correctly skips to 00 now after decoding, and signals this
592 as an End of Information itself)
606 while (code
!= ab_fin
);
608 delete [] ab_prefix
;
617 // Returns true if the file looks like a valid GIF, false otherwise.
619 bool wxGIFDecoder::CanRead()
621 unsigned char buf
[3];
623 if ( !m_f
->Read(buf
, WXSIZEOF(buf
)) )
626 m_f
->SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
);
628 return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0;
633 // Reads and decodes one or more GIF images, depending on whether
634 // animated GIF support is enabled. Can read GIFs with any bit
635 // size (color depth), but the output images are always expanded
636 // to 8 bits per pixel. Also, the image palettes always contain
637 // 256 colors, although some of them may be unused. Returns wxGIF_OK
638 // (== 0) on success, or an error code if something fails (see
639 // header file for details)
641 int wxGIFDecoder::ReadGIF()
643 unsigned int ncolors
;
644 int bits
, interl
, transparent
, disposal
, i
;
647 unsigned char type
= 0;
648 unsigned char pal
[768];
649 unsigned char buf
[16];
651 GIFImage
*pimg
, *pprev
;
653 /* check GIF signature */
655 return wxGIF_INVFORMAT
;
657 /* check for animated GIF support (ver. >= 89a) */
659 static const size_t headerSize
= (3 + 3);
660 m_f
->Read(buf
, headerSize
);
661 if (m_f
->LastRead() != headerSize
)
663 return wxGIF_INVFORMAT
;
666 if (memcmp(buf
+ 3, "89a", 3) < 0)
671 /* read logical screen descriptor block (LSDB) */
672 static const size_t lsdbSize
= (2 + 2 + 1 + 1 + 1);
673 m_f
->Read(buf
, lsdbSize
);
674 if (m_f
->LastRead() != lsdbSize
)
676 return wxGIF_INVFORMAT
;
679 m_screenw
= buf
[0] + 256 * buf
[1];
680 m_screenh
= buf
[2] + 256 * buf
[3];
682 /* load global color map if available */
683 if ((buf
[4] & 0x80) == 0x80)
685 m_background
= buf
[5];
687 ncolors
= 2 << (buf
[4] & 0x07);
688 size_t numBytes
= 3 * ncolors
;
689 m_f
->Read(pal
, numBytes
);
690 if (m_f
->LastRead() != numBytes
)
692 return wxGIF_INVFORMAT
;
696 /* transparent colour, disposal method and delay default to unused */
710 type
= (unsigned char)m_f
->GetC();
713 If the end of file has been reached (or an error) and a ";"
714 (0x3B) hasn't been encountered yet, exit the loop. (Without this
715 check the while loop would loop endlessly.) Later on, in the next while
716 loop, the file will be treated as being truncated (But still
717 be decoded as far as possible). returning wxGIF_TRUNCATED is not
718 possible here since some init code is done after this loop.
720 if (m_f
->Eof())// || !m_f->IsOk())
723 type is set to some bogus value, so there's no
724 need to continue evaluating it.
726 break; // Alternative : "return wxGIF_INVFORMAT;"
735 /* extension block? */
738 if (((unsigned char)m_f
->GetC()) == 0xF9)
739 /* graphics control extension, parse it */
741 static const size_t gceSize
= 6;
742 m_f
->Read(buf
, gceSize
);
743 if (m_f
->LastRead() != gceSize
)
746 return wxGIF_INVFORMAT
;
749 /* read delay and convert from 1/100 of a second to ms */
750 delay
= 10 * (buf
[2] + 256 * buf
[3]);
752 /* read transparent colour index, if used */
754 transparent
= buf
[4];
756 /* read disposal method */
757 disposal
= ((buf
[1] & 0x1C) >> 2) - 1;
760 /* other extension, skip */
762 while ((i
= (unsigned char)m_f
->GetC()) != 0)
764 m_f
->SeekI(i
, wxFromCurrent
);
774 /* image descriptor block? */
777 /* allocate memory for IMAGEN struct */
778 pimg
= (*ppimg
) = new GIFImage();
786 /* fill in the data */
787 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
788 m_f
->Read(buf
, idbSize
);
789 if (m_f
->LastRead() != idbSize
)
792 return wxGIF_INVFORMAT
;
795 pimg
->left
= buf
[0] + 256 * buf
[1];
796 pimg
->top
= buf
[2] + 256 * buf
[3];
798 pimg->left = buf[4] + 256 * buf[5];
799 pimg->top = buf[4] + 256 * buf[5];
801 pimg
->w
= buf
[4] + 256 * buf
[5];
802 pimg
->h
= buf
[6] + 256 * buf
[7];
804 if (pimg
->w
== 0 || pimg
->h
== 0)
807 return wxGIF_INVFORMAT
;
810 interl
= ((buf
[8] & 0x40)? 1 : 0);
811 size
= pimg
->w
* pimg
->h
;
813 pimg
->transparent
= transparent
;
814 pimg
->disposal
= disposal
;
821 /* allocate memory for image and palette */
822 pimg
->p
= (unsigned char *) malloc((size_t)size
);
823 pimg
->pal
= (unsigned char *) malloc(768);
825 if ((!pimg
->p
) || (!pimg
->pal
))
831 /* load local color map if available, else use global map */
832 if ((buf
[8] & 0x80) == 0x80)
834 ncolors
= 2 << (buf
[8] & 0x07);
835 size_t numBytes
= 3 * ncolors
;
836 m_f
->Read(pimg
->pal
, numBytes
);
837 if (m_f
->LastRead() != numBytes
)
840 return wxGIF_INVFORMAT
;
845 memcpy(pimg
->pal
, pal
, 768);
848 /* get initial code size from first byte in raster data */
849 bits
= (unsigned char)m_f
->GetC();
852 int result
= dgif(pimg
, interl
, bits
);
853 if (result
!= wxGIF_OK
)
860 /* if this is not an animated GIF, exit after first image */
869 return wxGIF_INVFORMAT
;
872 /* setup image pointers */
877 /* try to read to the end of the stream */
881 return wxGIF_TRUNCATED
;
883 type
= (unsigned char)m_f
->GetC();
891 while ((i
= (unsigned char)m_f
->GetC()) != 0)
893 m_f
->SeekI(i
, wxFromCurrent
);
896 else if (type
== 0x2C)
898 /* image descriptor block */
899 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
900 m_f
->Read(buf
, idbSize
);
901 if (m_f
->LastRead() != idbSize
)
904 return wxGIF_INVFORMAT
;
907 /* local color map */
908 if ((buf
[8] & 0x80) == 0x80)
910 ncolors
= 2 << (buf
[8] & 0x07);
911 wxFileOffset pos
= m_f
->TellI();
912 wxFileOffset numBytes
= 3 * ncolors
;
913 m_f
->SeekI(numBytes
, wxFromCurrent
);
914 if (m_f
->TellI() != (pos
+ numBytes
))
917 return wxGIF_INVFORMAT
;
921 /* initial code size */
925 while ((i
= (unsigned char)m_f
->GetC()) != 0)
927 m_f
->SeekI(i
, wxFromCurrent
);
930 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
932 /* images are OK, but couldn't read to the end of the stream */
933 return wxGIF_TRUNCATED
;
940 #endif // wxUSE_STREAMS && wxUSE_GIF