]>
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
);
130 // Palette creation not yet implemented on wxGTK
134 unsigned char* r
= new unsigned char[256];
135 unsigned char* g
= new unsigned char[256];
136 unsigned char* b
= new unsigned char[256];
137 for (i
= 0; i
< 256; i
++)
143 image
->SetPalette(wxPalette(256, r
, g
, b
));
144 delete[] r
; delete[] g
; delete[] b
;
148 /* copy image data */
149 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
151 *(dst
++) = pal
[3 * (*src
) + 0];
152 *(dst
++) = pal
[3 * (*src
) + 1];
153 *(dst
++) = pal
[3 * (*src
) + 2];
160 //---------------------------------------------------------------------------
162 //---------------------------------------------------------------------------
164 // Get data for current frame
166 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
167 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
168 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
169 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
170 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
171 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
172 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
173 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
174 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
175 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
179 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
180 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
181 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
182 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
183 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
186 //---------------------------------------------------------------------------
187 // Functions to move through the animation
188 //---------------------------------------------------------------------------
190 bool wxGIFDecoder::GoFirstFrame()
200 bool wxGIFDecoder::GoLastFrame()
210 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
215 if ((m_image
< m_nimages
) || (cyclic
))
217 m_pimage
= m_pimage
->next
;
232 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
237 if ((m_image
> 1) || (cyclic
))
239 m_pimage
= m_pimage
->prev
;
254 bool wxGIFDecoder::GoFrame(int which
)
261 if ((which
>= 1) && (which
<= m_nimages
))
265 for (i
= 1; i
< which
; i
++)
266 m_pimage
= m_pimage
->next
;
275 //---------------------------------------------------------------------------
276 // GIF reading and decoding
277 //---------------------------------------------------------------------------
280 // Reads the next code from the file stream, with size 'bits'
282 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
284 unsigned int mask
; /* bit mask */
285 unsigned int code
; /* code (result) */
288 /* get remaining bits from last byte read */
289 mask
= (1 << bits
) - 1;
290 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
292 /* keep reading new bytes while needed */
293 while (bits
> m_restbits
)
295 /* if no bytes left in this block, read the next block */
298 m_restbyte
= (unsigned char)m_f
->GetC();
300 /* Some encoders are a bit broken: instead of issuing
301 * an end-of-image symbol (ab_fin) they come up with
302 * a zero-length subblock!! We catch this here so
303 * that the decoder sees an ab_fin code.
312 m_f
->Read((void *) m_buffer
, m_restbyte
);
316 /* read next byte and isolate the bits we need */
317 m_lastbyte
= (unsigned char) (*m_bufp
++);
318 mask
= (1 << (bits
- m_restbits
)) - 1;
319 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
322 /* adjust total number of bits extracted from the buffer */
323 m_restbits
= m_restbits
+ 8;
326 /* find number of bits remaining for next code */
327 m_restbits
= (m_restbits
- bits
);
334 // GIF decoding function. The initial code size (aka root size)
335 // is 'bits'. Supports interlaced images (interl == 1).
337 int wxGIFDecoder::dgif(GIFImage
*img
, int interl
, int bits
)
340 int *ab_prefix
= new int[4096]; /* alphabet (prefixes) */
341 int *ab_tail
= new int[4096]; /* alphabet (tails) */
342 int *stack
= new int[4096]; /* decompression stack */
344 int ab_prefix
[4096]; /* alphabet (prefixes) */
345 int ab_tail
[4096]; /* alphabet (tails) */
346 int stack
[4096]; /* decompression stack */
348 int ab_clr
; /* clear code */
349 int ab_fin
; /* end of info code */
350 int ab_bits
; /* actual symbol width, in bits */
351 int ab_free
; /* first free position in alphabet */
352 int ab_max
; /* last possible character in alphabet */
353 int pass
; /* pass number in interlaced images */
354 int pos
; /* index into decompresion stack */
355 unsigned int x
, y
; /* position in image buffer */
357 int code
, readcode
, lastcode
, abcabca
;
359 /* these won't change */
360 ab_clr
= (1 << bits
);
361 ab_fin
= (1 << bits
) + 1;
363 /* these will change through the decompression proccess */
365 ab_free
= (1 << bits
) + 2;
366 ab_max
= (1 << ab_bits
) - 1;
372 /* reset decoder vars */
380 readcode
= code
= getcode(ab_bits
, ab_fin
);
383 if (code
== ab_fin
) break;
385 /* reset alphabet? */
388 /* reset main variables */
390 ab_free
= (1 << bits
) + 2;
391 ab_max
= (1 << ab_bits
) - 1;
395 /* skip to next code */
399 /* unknown code: special case (like in ABCABCA) */
402 code
= lastcode
; /* take last string */
403 stack
[pos
++] = abcabca
; /* add first character */
406 /* build the string for this code in the stack */
407 while (code
> ab_clr
)
409 stack
[pos
++] = ab_tail
[code
];
410 code
= ab_prefix
[code
];
412 stack
[pos
] = code
; /* push last code into the stack */
413 abcabca
= code
; /* save for special case */
415 /* make new entry in alphabet (only if NOT just cleared) */
418 ab_prefix
[ab_free
] = lastcode
;
419 ab_tail
[ab_free
] = code
;
422 if ((ab_free
> ab_max
) && (ab_bits
< 12))
425 ab_max
= (1 << ab_bits
) - 1;
429 /* dump stack data to the buffer */
432 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
440 /* support for interlaced images */
443 case 1: y
+= 8; break;
444 case 2: y
+= 8; break;
445 case 3: y
+= 4; break;
446 case 4: y
+= 2; break;
452 case 2: y
= 4; break;
453 case 3: y
= 2; break;
454 case 4: y
= 1; break;
469 while (code
!= ab_fin
);
472 delete [] ab_prefix
;
481 // Returns TRUE if the file looks like a valid GIF, FALSE otherwise.
483 bool wxGIFDecoder::CanRead()
485 unsigned char buf
[3];
488 m_f
->SeekI(-3, wxFromCurrent
);
490 return (memcmp(buf
, "GIF", 3) == 0);
495 // Reads and decodes one or more GIF images, depending on whether
496 // animated GIF support is enabled. Can read GIFs with any bit
497 // size (color depth), but the output images are always expanded
498 // to 8 bits per pixel. Also, the image palettes always contain
499 // 256 colors, although some of them may be unused. Returns wxGIF_OK
500 // (== 0) on success, or an error code if something fails (see
501 // header file for details)
503 int wxGIFDecoder::ReadGIF()
505 int ncolors
, bits
, interl
, transparent
, disposal
, i
;
508 unsigned char type
= 0;
509 unsigned char pal
[768];
510 unsigned char buf
[16];
511 GIFImage
**ppimg
, *pimg
, *pprev
;
513 /* check GIF signature */
515 return wxGIF_INVFORMAT
;
517 /* check for animated GIF support (ver. >= 89a) */
520 if (memcmp(buf
+ 3, "89a", 3) < 0)
523 /* read logical screen descriptor block (LSDB) */
525 m_screenw
= buf
[0] + 256 * buf
[1];
526 m_screenh
= buf
[2] + 256 * buf
[3];
528 /* load global color map if available */
529 if ((buf
[4] & 0x80) == 0x80)
531 m_background
= buf
[5];
533 ncolors
= 2 << (buf
[4] & 0x07);
534 m_f
->Read(pal
, 3 * ncolors
);
537 /* transparent colour, disposal method and delay default to unused */
551 type
= (unsigned char)m_f
->GetC();
559 /* extension block? */
562 if (((unsigned char)m_f
->GetC()) == 0xF9)
563 /* graphics control extension, parse it */
567 /* read delay and convert from 1/100 of a second to ms */
568 delay
= 10 * (buf
[2] + 256 * buf
[3]);
570 /* read transparent colour index, if used */
572 transparent
= buf
[4];
574 /* read disposal method */
575 disposal
= (buf
[1] & 0x1C) - 1;
578 /* other extension, skip */
580 while ((i
= (unsigned char)m_f
->GetC()) != 0)
582 m_f
->SeekI(i
, wxFromCurrent
);
587 /* image descriptor block? */
590 /* allocate memory for IMAGEN struct */
591 pimg
= (*ppimg
) = new GIFImage();
599 /* fill in the data */
601 pimg
->left
= buf
[4] + 256 * buf
[5];
602 pimg
->top
= buf
[4] + 256 * buf
[5];
603 pimg
->w
= buf
[4] + 256 * buf
[5];
604 pimg
->h
= buf
[6] + 256 * buf
[7];
605 interl
= ((buf
[8] & 0x40)? 1 : 0);
606 size
= pimg
->w
* pimg
->h
;
608 pimg
->transparent
= transparent
;
609 pimg
->disposal
= disposal
;
616 /* allocate memory for image and palette */
617 pimg
->p
= (unsigned char *) malloc((size_t)size
);
618 pimg
->pal
= (unsigned char *) malloc(768);
620 if ((!pimg
->p
) || (!pimg
->pal
))
626 /* load local color map if available, else use global map */
627 if ((buf
[8] & 0x80) == 0x80)
629 ncolors
= 2 << (buf
[8] & 0x07);
630 m_f
->Read(pimg
->pal
, 3 * ncolors
);
633 memcpy(pimg
->pal
, pal
, 768);
635 /* get initial code size from first byte in raster data */
636 bits
= (unsigned char)m_f
->GetC();
639 dgif(pimg
, interl
, bits
);
642 /* if this is not an animated GIF, exit after first image */
648 /* setup image pointers */
656 /* try to read to the end of the stream */
659 type
= (unsigned char)m_f
->GetC();
667 while ((i
= (unsigned char)m_f
->GetC()) != 0)
669 m_f
->SeekI(i
, wxFromCurrent
);
672 else if (type
== 0x2C)
674 /* image descriptor block */
677 /* local color map */
678 if ((buf
[8] & 0x80) == 0x80)
680 ncolors
= 2 << (buf
[8] & 0x07);
681 m_f
->SeekI(3 * ncolors
, wxFromCurrent
);
684 /* initial code size */
688 while ((i
= (unsigned char)m_f
->GetC()) != 0)
690 m_f
->SeekI(i
, wxFromCurrent
);
693 else if ((type
!= 0x3B) && (type
!= 00)) /* testing */
695 /* images are OK, but couldn't read to the end of the stream */
696 return wxGIF_TRUNCATED
;
703 #endif // wxUSE_STREAMS && wxUSE_GIF