]>
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 // wxGIFDecoder constructor and destructor
35 //---------------------------------------------------------------------------
37 wxGIFDecoder::wxGIFDecoder(wxInputStream
*s
, bool anim
)
53 wxGIFDecoder::~wxGIFDecoder()
58 void wxGIFDecoder::Destroy()
60 GIFImage
*pimg
, *paux
;
81 //---------------------------------------------------------------------------
82 // Convert this image to a wxImage object
83 //---------------------------------------------------------------------------
85 // This function was designed by Vaclav Slavik
87 bool wxGIFDecoder::ConvertToImage(wxImage
*image
) const
89 unsigned char *src
, *dst
, *pal
;
96 /* create the image */
97 image
->Create(GetWidth(), GetHeight());
104 dst
= image
->GetData();
105 transparent
= GetTransparentColour();
107 /* set transparent colour mask */
108 if (transparent
!= -1)
110 for (i
= 0; i
< 256; i
++)
112 if ((pal
[3 * i
+ 0] == 255) &&
113 (pal
[3 * i
+ 1] == 0) &&
114 (pal
[3 * i
+ 2] == 255))
116 pal
[3 * i
+ 2] = 254;
120 pal
[3 * transparent
+ 0] = 255,
121 pal
[3 * transparent
+ 1] = 0,
122 pal
[3 * transparent
+ 2] = 255;
124 image
->SetMaskColour(255, 0, 255);
127 image
->SetMask(FALSE
);
132 unsigned char r
[256];
133 unsigned char g
[256];
134 unsigned char b
[256];
136 for (i
= 0; i
< 256; i
++)
143 image
->SetPalette(wxPalette(256, r
, g
, b
));
145 #endif // wxUSE_PALETTE
147 /* copy image data */
148 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
150 *(dst
++) = pal
[3 * (*src
) + 0];
151 *(dst
++) = pal
[3 * (*src
) + 1];
152 *(dst
++) = pal
[3 * (*src
) + 2];
159 //---------------------------------------------------------------------------
161 //---------------------------------------------------------------------------
163 // Get data for current frame
165 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
166 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
167 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
168 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
169 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
170 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
171 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
172 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
173 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
174 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
178 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
179 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
180 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
181 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
182 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
185 //---------------------------------------------------------------------------
186 // Functions to move through the animation
187 //---------------------------------------------------------------------------
189 bool wxGIFDecoder::GoFirstFrame()
199 bool wxGIFDecoder::GoLastFrame()
209 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
214 if ((m_image
< m_nimages
) || (cyclic
))
216 m_pimage
= m_pimage
->next
;
231 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
236 if ((m_image
> 1) || (cyclic
))
238 m_pimage
= m_pimage
->prev
;
253 bool wxGIFDecoder::GoFrame(int which
)
260 if ((which
>= 1) && (which
<= m_nimages
))
264 for (i
= 1; i
< which
; i
++)
265 m_pimage
= m_pimage
->next
;
274 //---------------------------------------------------------------------------
275 // GIF reading and decoding
276 //---------------------------------------------------------------------------
279 // Reads the next code from the file stream, with size 'bits'
281 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
283 unsigned int mask
; /* bit mask */
284 unsigned int code
; /* code (result) */
287 /* get remaining bits from last byte read */
288 mask
= (1 << bits
) - 1;
289 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
291 /* keep reading new bytes while needed */
292 while (bits
> m_restbits
)
294 /* if no bytes left in this block, read the next block */
297 m_restbyte
= (unsigned char)m_f
->GetC();
299 /* Some encoders are a bit broken: instead of issuing
300 * an end-of-image symbol (ab_fin) they come up with
301 * a zero-length subblock!! We catch this here so
302 * that the decoder sees an ab_fin code.
311 m_f
->Read((void *) m_buffer
, m_restbyte
);
315 /* read next byte and isolate the bits we need */
316 m_lastbyte
= (unsigned char) (*m_bufp
++);
317 mask
= (1 << (bits
- m_restbits
)) - 1;
318 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
321 /* adjust total number of bits extracted from the buffer */
322 m_restbits
= m_restbits
+ 8;
325 /* find number of bits remaining for next code */
326 m_restbits
= (m_restbits
- bits
);
333 // GIF decoding function. The initial code size (aka root size)
334 // is 'bits'. Supports interlaced images (interl == 1).
336 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
338 int *ab_prefix
= new int[4096]; /* alphabet (prefixes) */
339 int *ab_tail
= new int[4096]; /* alphabet (tails) */
340 int *stack
= new int[4096]; /* decompression stack */
341 int ab_clr
; /* clear code */
342 int ab_fin
; /* end of info code */
343 int ab_bits
; /* actual symbol width, in bits */
344 int ab_free
; /* first free position in alphabet */
345 int ab_max
; /* last possible character in alphabet */
346 int pass
; /* pass number in interlaced images */
347 int pos
; /* index into decompresion stack */
348 unsigned int x
, y
; /* position in image buffer */
350 int code
, readcode
, lastcode
, abcabca
;
352 /* these won't change */
353 ab_clr
= (1 << bits
);
354 ab_fin
= (1 << bits
) + 1;
356 /* these will change through the decompression proccess */
358 ab_free
= (1 << bits
) + 2;
359 ab_max
= (1 << ab_bits
) - 1;
365 /* reset decoder vars */
373 readcode
= code
= getcode(ab_bits
, ab_fin
);
376 if (code
== ab_fin
) break;
378 /* reset alphabet? */
381 /* reset main variables */
383 ab_free
= (1 << bits
) + 2;
384 ab_max
= (1 << ab_bits
) - 1;
388 /* skip to next code */
392 /* unknown code: special case (like in ABCABCA) */
395 code
= lastcode
; /* take last string */
396 stack
[pos
++] = abcabca
; /* add first character */
399 /* build the string for this code in the stack */
400 while (code
> ab_clr
)
402 stack
[pos
++] = ab_tail
[code
];
403 code
= ab_prefix
[code
];
405 stack
[pos
] = code
; /* push last code into the stack */
406 abcabca
= code
; /* save for special case */
408 /* make new entry in alphabet (only if NOT just cleared) */
411 ab_prefix
[ab_free
] = lastcode
;
412 ab_tail
[ab_free
] = code
;
415 if ((ab_free
> ab_max
) && (ab_bits
< 12))
418 ab_max
= (1 << ab_bits
) - 1;
422 /* dump stack data to the buffer */
425 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
433 /* support for interlaced images */
436 case 1: y
+= 8; break;
437 case 2: y
+= 8; break;
438 case 3: y
+= 4; break;
439 case 4: y
+= 2; break;
445 case 2: y
= 4; break;
446 case 3: y
= 2; break;
447 case 4: y
= 1; break;
456 Normally image decoding is finished when an End of Information code is
457 encountered (code == ab_fin) however some broken encoders write wrong
458 "block byte counts" (The first byte value after the "code size" byte),
459 being one value too high. It might very well be possible other variants
460 of this problem occur as well. The only sensible solution seems to
461 be to check for clipping.
462 Example of wrong encoding:
463 (1 * 1 B/W image, raster data stream follows in hex bytes)
465 02 << B/W images have a code size of 2
466 02 << Block byte count
468 00 << Zero byte count (terminates data stream)
470 Because the block byte count is 2, the zero byte count is used in the
471 decoding process, and decoding is continued after this byte. (While it
472 should signal an end of image)
478 01 << When decoded this correctly includes the End of Information code
486 (The 44 doesn't include an End of Information code, but at least the
487 decoder correctly skips to 00 now after decoding, and signals this
488 as an End of Information itself)
502 while (code
!= ab_fin
);
504 delete [] ab_prefix
;
513 // Returns TRUE if the file looks like a valid GIF, FALSE otherwise.
515 bool wxGIFDecoder::CanRead()
517 unsigned char buf
[3];
520 m_f
->SeekI(-3, wxFromCurrent
);
522 return (memcmp(buf
, "GIF", 3) == 0);
527 // Reads and decodes one or more GIF images, depending on whether
528 // animated GIF support is enabled. Can read GIFs with any bit
529 // size (color depth), but the output images are always expanded
530 // to 8 bits per pixel. Also, the image palettes always contain
531 // 256 colors, although some of them may be unused. Returns wxGIF_OK
532 // (== 0) on success, or an error code if something fails (see
533 // header file for details)
535 int wxGIFDecoder::ReadGIF()
537 int ncolors
, bits
, interl
, transparent
, disposal
, i
;
540 unsigned char type
= 0;
541 unsigned char pal
[768];
542 unsigned char buf
[16];
544 GIFImage
*pimg
, *pprev
;
546 /* check GIF signature */
548 return wxGIF_INVFORMAT
;
550 /* check for animated GIF support (ver. >= 89a) */
553 if (memcmp(buf
+ 3, "89a", 3) < 0)
556 /* read logical screen descriptor block (LSDB) */
558 m_screenw
= buf
[0] + 256 * buf
[1];
559 m_screenh
= buf
[2] + 256 * buf
[3];
561 /* load global color map if available */
562 if ((buf
[4] & 0x80) == 0x80)
564 m_background
= buf
[5];
566 ncolors
= 2 << (buf
[4] & 0x07);
567 m_f
->Read(pal
, 3 * ncolors
);
570 /* transparent colour, disposal method and delay default to unused */
584 type
= (unsigned char)m_f
->GetC();
592 /* extension block? */
595 if (((unsigned char)m_f
->GetC()) == 0xF9)
596 /* graphics control extension, parse it */
600 /* read delay and convert from 1/100 of a second to ms */
601 delay
= 10 * (buf
[2] + 256 * buf
[3]);
603 /* read transparent colour index, if used */
605 transparent
= buf
[4];
607 /* read disposal method */
608 disposal
= (buf
[1] & 0x1C) - 1;
611 /* other extension, skip */
613 while ((i
= (unsigned char)m_f
->GetC()) != 0)
615 m_f
->SeekI(i
, wxFromCurrent
);
620 /* image descriptor block? */
623 /* allocate memory for IMAGEN struct */
624 pimg
= (*ppimg
) = new GIFImage();
632 /* fill in the data */
634 pimg
->left
= buf
[0] + 256 * buf
[1];
635 pimg
->top
= buf
[2] + 256 * buf
[3];
637 pimg->left = buf[4] + 256 * buf[5];
638 pimg->top = buf[4] + 256 * buf[5];
640 pimg
->w
= buf
[4] + 256 * buf
[5];
641 pimg
->h
= buf
[6] + 256 * buf
[7];
642 interl
= ((buf
[8] & 0x40)? 1 : 0);
643 size
= pimg
->w
* pimg
->h
;
645 pimg
->transparent
= transparent
;
646 pimg
->disposal
= disposal
;
653 /* allocate memory for image and palette */
654 pimg
->p
= (unsigned char *) malloc((size_t)size
);
655 pimg
->pal
= (unsigned char *) malloc(768);
657 if ((!pimg
->p
) || (!pimg
->pal
))
663 /* load local color map if available, else use global map */
664 if ((buf
[8] & 0x80) == 0x80)
666 ncolors
= 2 << (buf
[8] & 0x07);
667 m_f
->Read(pimg
->pal
, 3 * ncolors
);
670 memcpy(pimg
->pal
, pal
, 768);
672 /* get initial code size from first byte in raster data */
673 bits
= (unsigned char)m_f
->GetC();
676 dgif(pimg
, interl
, bits
);
679 /* if this is not an animated GIF, exit after first image */
685 /* setup image pointers */
693 /* try to read to the end of the stream */
697 return wxGIF_TRUNCATED
;
699 type
= (unsigned char)m_f
->GetC();
707 while ((i
= (unsigned char)m_f
->GetC()) != 0)
709 m_f
->SeekI(i
, wxFromCurrent
);
712 else if (type
== 0x2C)
714 /* image descriptor block */
717 /* local color map */
718 if ((buf
[8] & 0x80) == 0x80)
720 ncolors
= 2 << (buf
[8] & 0x07);
721 m_f
->SeekI(3 * ncolors
, wxFromCurrent
);
724 /* initial code size */
728 while ((i
= (unsigned char)m_f
->GetC()) != 0)
730 m_f
->SeekI(i
, wxFromCurrent
);
733 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
735 /* images are OK, but couldn't read to the end of the stream */
736 return wxGIF_TRUNCATED
;
743 #endif // wxUSE_STREAMS && wxUSE_GIF