]>
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 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "gifdecod.h"
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
26 #if wxUSE_STREAMS && wxUSE_GIF
30 #include "wx/gifdecod.h"
33 //---------------------------------------------------------------------------
34 // GIFImage constructor
35 //---------------------------------------------------------------------------
45 p
= (unsigned char *) NULL
;
46 pal
= (unsigned char *) NULL
;
47 next
= (GIFImage
*) NULL
;
48 prev
= (GIFImage
*) NULL
;
51 //---------------------------------------------------------------------------
52 // wxGIFDecoder constructor and destructor
53 //---------------------------------------------------------------------------
55 wxGIFDecoder::wxGIFDecoder(wxInputStream
*s
, bool anim
)
71 wxGIFDecoder::~wxGIFDecoder()
76 void wxGIFDecoder::Destroy()
78 GIFImage
*pimg
, *paux
;
99 //---------------------------------------------------------------------------
100 // Convert this image to a wxImage object
101 //---------------------------------------------------------------------------
103 // This function was designed by Vaclav Slavik
105 bool wxGIFDecoder::ConvertToImage(wxImage
*image
) const
107 unsigned char *src
, *dst
, *pal
;
111 /* just in case... */
114 /* create the image */
115 image
->Create(GetWidth(), GetHeight());
122 dst
= image
->GetData();
123 transparent
= GetTransparentColour();
125 /* set transparent colour mask */
126 if (transparent
!= -1)
128 for (i
= 0; i
< 256; i
++)
130 if ((pal
[3 * i
+ 0] == 255) &&
131 (pal
[3 * i
+ 1] == 0) &&
132 (pal
[3 * i
+ 2] == 255))
134 pal
[3 * i
+ 2] = 254;
138 pal
[3 * transparent
+ 0] = 255,
139 pal
[3 * transparent
+ 1] = 0,
140 pal
[3 * transparent
+ 2] = 255;
142 image
->SetMaskColour(255, 0, 255);
145 image
->SetMask(FALSE
);
150 unsigned char r
[256];
151 unsigned char g
[256];
152 unsigned char b
[256];
154 for (i
= 0; i
< 256; i
++)
161 image
->SetPalette(wxPalette(256, r
, g
, b
));
163 #endif // wxUSE_PALETTE
165 /* copy image data */
166 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
168 *(dst
++) = pal
[3 * (*src
) + 0];
169 *(dst
++) = pal
[3 * (*src
) + 1];
170 *(dst
++) = pal
[3 * (*src
) + 2];
177 //---------------------------------------------------------------------------
179 //---------------------------------------------------------------------------
181 // Get data for current frame
183 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
184 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
185 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
186 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
187 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
188 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
189 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
190 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
191 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
192 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
196 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
197 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
198 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
199 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
200 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
203 //---------------------------------------------------------------------------
204 // Functions to move through the animation
205 //---------------------------------------------------------------------------
207 bool wxGIFDecoder::GoFirstFrame()
217 bool wxGIFDecoder::GoLastFrame()
227 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
232 if ((m_image
< m_nimages
) || (cyclic
))
234 m_pimage
= m_pimage
->next
;
249 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
254 if ((m_image
> 1) || (cyclic
))
256 m_pimage
= m_pimage
->prev
;
271 bool wxGIFDecoder::GoFrame(int which
)
278 if ((which
>= 1) && (which
<= m_nimages
))
282 for (i
= 1; i
< which
; i
++)
283 m_pimage
= m_pimage
->next
;
292 //---------------------------------------------------------------------------
293 // GIF reading and decoding
294 //---------------------------------------------------------------------------
297 // Reads the next code from the file stream, with size 'bits'
299 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
301 unsigned int mask
; /* bit mask */
302 unsigned int code
; /* code (result) */
305 /* get remaining bits from last byte read */
306 mask
= (1 << bits
) - 1;
307 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
309 /* keep reading new bytes while needed */
310 while (bits
> m_restbits
)
312 /* if no bytes left in this block, read the next block */
315 m_restbyte
= (unsigned char)m_f
->GetC();
317 /* Some encoders are a bit broken: instead of issuing
318 * an end-of-image symbol (ab_fin) they come up with
319 * a zero-length subblock!! We catch this here so
320 * that the decoder sees an ab_fin code.
329 m_f
->Read((void *) m_buffer
, m_restbyte
);
330 if (m_f
->LastRead() != m_restbyte
)
338 /* read next byte and isolate the bits we need */
339 m_lastbyte
= (unsigned char) (*m_bufp
++);
340 mask
= (1 << (bits
- m_restbits
)) - 1;
341 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
344 /* adjust total number of bits extracted from the buffer */
345 m_restbits
= m_restbits
+ 8;
348 /* find number of bits remaining for next code */
349 m_restbits
= (m_restbits
- bits
);
356 // GIF decoding function. The initial code size (aka root size)
357 // is 'bits'. Supports interlaced images (interl == 1).
358 // Returns wxGIF_OK (== 0) on success, or an error code if something
359 // fails (see header file for details)
360 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
362 static const int allocSize
= 4096 + 1;
363 int *ab_prefix
= new int[allocSize
]; /* alphabet (prefixes) */
364 if (ab_prefix
== NULL
)
369 int *ab_tail
= new int[allocSize
]; /* alphabet (tails) */
376 int *stack
= new int[allocSize
]; /* decompression stack */
384 int ab_clr
; /* clear code */
385 int ab_fin
; /* end of info code */
386 int ab_bits
; /* actual symbol width, in bits */
387 int ab_free
; /* first free position in alphabet */
388 int ab_max
; /* last possible character in alphabet */
389 int pass
; /* pass number in interlaced images */
390 int pos
; /* index into decompresion stack */
391 unsigned int x
, y
; /* position in image buffer */
393 int code
, readcode
, lastcode
, abcabca
;
395 /* these won't change */
396 ab_clr
= (1 << bits
);
397 ab_fin
= (1 << bits
) + 1;
399 /* these will change through the decompression proccess */
401 ab_free
= (1 << bits
) + 2;
402 ab_max
= (1 << ab_bits
) - 1;
408 /* reset decoder vars */
416 readcode
= code
= getcode(ab_bits
, ab_fin
);
419 if (code
== ab_fin
) break;
421 /* reset alphabet? */
424 /* reset main variables */
426 ab_free
= (1 << bits
) + 2;
427 ab_max
= (1 << ab_bits
) - 1;
431 /* skip to next code */
435 /* unknown code: special case (like in ABCABCA) */
438 code
= lastcode
; /* take last string */
439 stack
[pos
++] = abcabca
; /* add first character */
442 /* build the string for this code in the stack */
443 while (code
> ab_clr
)
445 stack
[pos
++] = ab_tail
[code
];
446 code
= ab_prefix
[code
];
448 // Don't overflow. This shouldn't happen with normal
449 // GIF files, the allocSize of 4096+1 is enough. This
450 // will only happen with badly formed GIFs.
451 if (pos
>= allocSize
)
456 return wxGIF_INVFORMAT
;
460 if (pos
>= allocSize
)
465 return wxGIF_INVFORMAT
;
468 stack
[pos
] = code
; /* push last code into the stack */
469 abcabca
= code
; /* save for special case */
471 /* make new entry in alphabet (only if NOT just cleared) */
474 ab_prefix
[ab_free
] = lastcode
;
475 ab_tail
[ab_free
] = code
;
478 if ((ab_free
> ab_max
) && (ab_bits
< 12))
481 ab_max
= (1 << ab_bits
) - 1;
485 /* dump stack data to the image buffer */
488 (img
->p
)[x
+ (y
* (img
->w
))] = (char) stack
[pos
];
497 /* support for interlaced images */
500 case 1: y
+= 8; break;
501 case 2: y
+= 8; break;
502 case 3: y
+= 4; break;
503 case 4: y
+= 2; break;
506 /* loop until a valid y coordinate has been
507 found, Or if the maximum number of passes has
508 been reached, exit the loop, and stop image
509 decoding (At this point the image is succesfully
511 If we don't loop, but merely set y to some other
512 value, that new value might still be invalid depending
513 on the height of the image. This would cause out of
516 while (y
>= (img
->h
))
520 case 2: y
= 4; break;
521 case 3: y
= 2; break;
522 case 4: y
= 1; break;
526 It's possible we arrive here. For example this
527 happens when the image is interlaced, and the
528 height is 1. Looking at the above cases, the
529 lowest possible y is 1. While the only valid
530 one would be 0 for an image of height 1. So
531 'eventually' the loop will arrive here.
532 This case makes sure this while loop is
533 exited, as well as the 2 other ones.
536 // Set y to a valid coordinate so the local
537 // while loop will be exited. (y = 0 always
538 // is >= img->h since if img->h == 0 the
539 // image is never decoded)
542 // This will exit the other outer while loop
545 // This will halt image decoding.
557 Normally image decoding is finished when an End of Information code is
558 encountered (code == ab_fin) however some broken encoders write wrong
559 "block byte counts" (The first byte value after the "code size" byte),
560 being one value too high. It might very well be possible other variants
561 of this problem occur as well. The only sensible solution seems to
562 be to check for clipping.
563 Example of wrong encoding:
564 (1 * 1 B/W image, raster data stream follows in hex bytes)
566 02 << B/W images have a code size of 2
567 02 << Block byte count
569 00 << Zero byte count (terminates data stream)
571 Because the block byte count is 2, the zero byte count is used in the
572 decoding process, and decoding is continued after this byte. (While it
573 should signal an end of image)
579 01 << When decoded this correctly includes the End of Information code
587 (The 44 doesn't include an End of Information code, but at least the
588 decoder correctly skips to 00 now after decoding, and signals this
589 as an End of Information itself)
603 while (code
!= ab_fin
);
605 delete [] ab_prefix
;
614 // Returns TRUE if the file looks like a valid GIF, FALSE otherwise.
616 bool wxGIFDecoder::CanRead()
618 unsigned char buf
[3];
621 m_f
->SeekI(-3, wxFromCurrent
);
623 return (memcmp(buf
, "GIF", 3) == 0);
628 // Reads and decodes one or more GIF images, depending on whether
629 // animated GIF support is enabled. Can read GIFs with any bit
630 // size (color depth), but the output images are always expanded
631 // to 8 bits per pixel. Also, the image palettes always contain
632 // 256 colors, although some of them may be unused. Returns wxGIF_OK
633 // (== 0) on success, or an error code if something fails (see
634 // header file for details)
636 int wxGIFDecoder::ReadGIF()
638 unsigned int ncolors
;
639 int bits
, interl
, transparent
, disposal
, i
;
642 unsigned char type
= 0;
643 unsigned char pal
[768];
644 unsigned char buf
[16];
646 GIFImage
*pimg
, *pprev
;
648 /* check GIF signature */
650 return wxGIF_INVFORMAT
;
652 /* check for animated GIF support (ver. >= 89a) */
654 static const size_t headerSize
= (3 + 3);
655 m_f
->Read(buf
, headerSize
);
656 if (m_f
->LastRead() != headerSize
)
658 return wxGIF_INVFORMAT
;
661 if (memcmp(buf
+ 3, "89a", 3) < 0)
666 /* read logical screen descriptor block (LSDB) */
667 static const size_t lsdbSize
= (2 + 2 + 1 + 1 + 1);
668 m_f
->Read(buf
, lsdbSize
);
669 if (m_f
->LastRead() != lsdbSize
)
671 return wxGIF_INVFORMAT
;
674 m_screenw
= buf
[0] + 256 * buf
[1];
675 m_screenh
= buf
[2] + 256 * buf
[3];
677 /* load global color map if available */
678 if ((buf
[4] & 0x80) == 0x80)
680 m_background
= buf
[5];
682 ncolors
= 2 << (buf
[4] & 0x07);
683 size_t numBytes
= 3 * ncolors
;
684 m_f
->Read(pal
, numBytes
);
685 if (m_f
->LastRead() != numBytes
)
687 return wxGIF_INVFORMAT
;
691 /* transparent colour, disposal method and delay default to unused */
705 type
= (unsigned char)m_f
->GetC();
708 If the end of file has been reached (or an error) and a ";"
709 (0x3B) hasn't been encountered yet, exit the loop. (Without this
710 check the while loop would loop endlessly.) Later on, in the next while
711 loop, the file will be treated as being truncated (But still
712 be decoded as far as possible). returning wxGIF_TRUNCATED is not
713 possible here since some init code is done after this loop.
715 if (m_f
->Eof())// || !m_f->IsOk())
718 type is set to some bogus value, so there's no
719 need to continue evaluating it.
721 break; // Alternative : "return wxGIF_INVFORMAT;"
730 /* extension block? */
733 if (((unsigned char)m_f
->GetC()) == 0xF9)
734 /* graphics control extension, parse it */
736 static const size_t gceSize
= 6;
737 m_f
->Read(buf
, gceSize
);
738 if (m_f
->LastRead() != gceSize
)
741 return wxGIF_INVFORMAT
;
744 /* read delay and convert from 1/100 of a second to ms */
745 delay
= 10 * (buf
[2] + 256 * buf
[3]);
747 /* read transparent colour index, if used */
749 transparent
= buf
[4];
751 /* read disposal method */
752 disposal
= (buf
[1] & 0x1C) - 1;
755 /* other extension, skip */
757 while ((i
= (unsigned char)m_f
->GetC()) != 0)
759 m_f
->SeekI(i
, wxFromCurrent
);
769 /* image descriptor block? */
772 /* allocate memory for IMAGEN struct */
773 pimg
= (*ppimg
) = new GIFImage();
781 /* fill in the data */
782 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
783 m_f
->Read(buf
, idbSize
);
784 if (m_f
->LastRead() != idbSize
)
787 return wxGIF_INVFORMAT
;
790 pimg
->left
= buf
[0] + 256 * buf
[1];
791 pimg
->top
= buf
[2] + 256 * buf
[3];
793 pimg->left = buf[4] + 256 * buf[5];
794 pimg->top = buf[4] + 256 * buf[5];
796 pimg
->w
= buf
[4] + 256 * buf
[5];
797 pimg
->h
= buf
[6] + 256 * buf
[7];
799 if (pimg
->w
== 0 || pimg
->h
== 0)
802 return wxGIF_INVFORMAT
;
805 interl
= ((buf
[8] & 0x40)? 1 : 0);
806 size
= pimg
->w
* pimg
->h
;
808 pimg
->transparent
= transparent
;
809 pimg
->disposal
= disposal
;
816 /* allocate memory for image and palette */
817 pimg
->p
= (unsigned char *) malloc((size_t)size
);
818 pimg
->pal
= (unsigned char *) malloc(768);
820 if ((!pimg
->p
) || (!pimg
->pal
))
826 /* load local color map if available, else use global map */
827 if ((buf
[8] & 0x80) == 0x80)
829 ncolors
= 2 << (buf
[8] & 0x07);
830 size_t numBytes
= 3 * ncolors
;
831 m_f
->Read(pimg
->pal
, numBytes
);
832 if (m_f
->LastRead() != numBytes
)
835 return wxGIF_INVFORMAT
;
840 memcpy(pimg
->pal
, pal
, 768);
843 /* get initial code size from first byte in raster data */
844 bits
= (unsigned char)m_f
->GetC();
847 int result
= dgif(pimg
, interl
, bits
);
848 if (result
!= wxGIF_OK
)
855 /* if this is not an animated GIF, exit after first image */
864 return wxGIF_INVFORMAT
;
867 /* setup image pointers */
872 /* try to read to the end of the stream */
876 return wxGIF_TRUNCATED
;
878 type
= (unsigned char)m_f
->GetC();
886 while ((i
= (unsigned char)m_f
->GetC()) != 0)
888 m_f
->SeekI(i
, wxFromCurrent
);
891 else if (type
== 0x2C)
893 /* image descriptor block */
894 static const size_t idbSize
= (2 + 2 + 2 + 2 + 1);
895 m_f
->Read(buf
, idbSize
);
896 if (m_f
->LastRead() != idbSize
)
899 return wxGIF_INVFORMAT
;
902 /* local color map */
903 if ((buf
[8] & 0x80) == 0x80)
905 ncolors
= 2 << (buf
[8] & 0x07);
906 off_t pos
= m_f
->TellI();
907 off_t numBytes
= 3 * ncolors
;
908 m_f
->SeekI(numBytes
, wxFromCurrent
);
909 if (m_f
->TellI() != (pos
+ numBytes
))
912 return wxGIF_INVFORMAT
;
916 /* initial code size */
920 while ((i
= (unsigned char)m_f
->GetC()) != 0)
922 m_f
->SeekI(i
, wxFromCurrent
);
925 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
927 /* images are OK, but couldn't read to the end of the stream */
928 return wxGIF_TRUNCATED
;
935 #endif // wxUSE_STREAMS && wxUSE_GIF