]>
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>
6 // Last rev: 1999/08/14
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"
23 # include "wx/setup.h"
31 #include "wx/gifdecod.h"
34 //---------------------------------------------------------------------------
35 // wxGIFDecoder constructor and destructor
36 //---------------------------------------------------------------------------
38 wxGIFDecoder::wxGIFDecoder(wxInputStream
*s
, bool anim
)
54 wxGIFDecoder::~wxGIFDecoder()
59 void wxGIFDecoder::Destroy()
76 //---------------------------------------------------------------------------
77 // Convert this image to a wxImage object
78 //---------------------------------------------------------------------------
80 // This function was designed by Vaclav Slavik
82 bool wxGIFDecoder::ConvertToImage(wxImage
*image
) const
84 unsigned char *src
, *dst
, *pal
;
88 /* create the image */
89 image
->Create(GetWidth(), GetHeight());
96 dst
= image
->GetData();
97 transparent
= GetTransparentColour();
99 /* set transparent colour mask */
100 if (transparent
!= -1)
102 for (i
= 0; i
< 256; i
++)
104 if ((pal
[3 * i
+ 0] == 255) &&
105 (pal
[3 * i
+ 1] == 0) &&
106 (pal
[3 * i
+ 2] == 255))
108 pal
[3 * i
+ 2] = 254;
112 pal
[3 * transparent
+ 0] = 255,
113 pal
[3 * transparent
+ 1] = 0,
114 pal
[3 * transparent
+ 2] = 255;
116 image
->SetMaskColour(255, 0, 255);
119 image
->SetMask(FALSE
);
121 /* copy image data */
122 for (i
= 0; i
< (GetWidth() * GetHeight()); i
++, src
++)
124 *(dst
++) = pal
[3 * (*src
) + 0];
125 *(dst
++) = pal
[3 * (*src
) + 1];
126 *(dst
++) = pal
[3 * (*src
) + 2];
133 //---------------------------------------------------------------------------
135 //---------------------------------------------------------------------------
137 // Get data for current frame
139 int wxGIFDecoder::GetFrameIndex() const { return m_image
; }
140 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage
->p
); }
141 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); }
142 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage
->w
); }
143 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage
->h
); }
144 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage
->top
); }
145 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage
->left
); }
146 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage
->transparent
); }
147 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage
->disposal
); }
148 long wxGIFDecoder::GetDelay() const { return (m_pimage
->delay
); }
152 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw
; }
153 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh
; }
154 int wxGIFDecoder::GetBackgroundColour() const { return m_background
; }
155 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages
; }
156 bool wxGIFDecoder::IsAnimation() const { return (m_nimages
> 1); }
159 //---------------------------------------------------------------------------
160 // Functions to move through the animation
161 //---------------------------------------------------------------------------
163 bool wxGIFDecoder::GoFirstFrame()
173 bool wxGIFDecoder::GoLastFrame()
183 bool wxGIFDecoder::GoNextFrame(bool cyclic
)
188 if ((m_image
< m_nimages
) || (cyclic
))
190 m_pimage
= m_pimage
->next
;
205 bool wxGIFDecoder::GoPrevFrame(bool cyclic
)
210 if ((m_image
> 1) || (cyclic
))
212 m_pimage
= m_pimage
->prev
;
227 bool wxGIFDecoder::GoFrame(int which
)
234 if ((which
>= 1) && (which
<= m_nimages
))
238 for (i
= 1; i
< which
; i
++)
239 m_pimage
= m_pimage
->next
;
248 //---------------------------------------------------------------------------
249 // GIF reading and decoding
250 //---------------------------------------------------------------------------
253 // Reads the next code from the file stream, with size 'bits'
255 int wxGIFDecoder::getcode(int bits
, int ab_fin
)
257 unsigned int mask
; /* bit mask */
258 unsigned int code
; /* code (result) */
261 /* get remaining bits from last byte read */
262 mask
= (1 << bits
) - 1;
263 code
= (m_lastbyte
>> (8 - m_restbits
)) & mask
;
265 /* keep reading new bytes while needed */
266 while (bits
> m_restbits
)
268 /* if no bytes left in this block, read the next block */
271 m_restbyte
= (unsigned char)m_f
->GetC();
273 /* Some encoders are a bit broken: instead of issuing
274 * an end-of-image symbol (ab_fin) they come up with
275 * a zero-length subblock!! We catch this here so
276 * that the decoder sees an ab_fin code.
285 /* read next byte and isolate the bits we need */
286 m_lastbyte
= (unsigned char)m_f
->GetC();
287 mask
= (1 << (bits
- m_restbits
)) - 1;
288 code
= code
+ ((m_lastbyte
& mask
) << m_restbits
);
291 /* adjust total number of bits extracted from the buffer */
292 m_restbits
= m_restbits
+ 8;
295 /* find number of bits remaining for next code */
296 m_restbits
= (m_restbits
- bits
);
303 // GIF decoding function. The initial code size (aka root size)
304 // is 'bits'. Supports interlaced images (interl == 1).
306 int wxGIFDecoder::dgif(IMAGEN
*img
, int interl
, int bits
)
308 int ab_prefix
[4096]; /* alphabet (prefixes) */
309 int ab_tail
[4096]; /* alphabet (tails) */
310 int stack
[4096]; /* decompression stack */
312 int ab_clr
; /* clear code */
313 int ab_fin
; /* end of info code */
314 int ab_bits
; /* actual symbol width, in bits */
315 int ab_free
; /* first free position in alphabet */
316 int ab_max
; /* last possible character in alphabet */
317 int pass
; /* pass number in interlaced images */
318 int pos
; /* index into decompresion stack */
319 unsigned int x
, y
; /* position in image buffer */
321 int code
, readcode
, lastcode
, abcabca
;
323 /* these won't change */
324 ab_clr
= (1 << bits
);
325 ab_fin
= (1 << bits
) + 1;
327 /* these will change through the decompression proccess */
329 ab_free
= (1 << bits
) + 2;
330 ab_max
= (1 << ab_bits
) - 1;
336 /* reset static globals */
344 readcode
= code
= getcode(ab_bits
, ab_fin
);
347 if (code
== ab_fin
) break;
349 /* reset alphabet? */
352 /* reset main variables */
354 ab_free
= (1 << bits
) + 2;
355 ab_max
= (1 << ab_bits
) - 1;
359 /* skip to next code */
363 /* unknown code: special case (like in ABCABCA) */
366 code
= lastcode
; /* take last string */
367 stack
[pos
++] = abcabca
; /* add first character */
370 /* build the string for this code in the stack */
371 while (code
> ab_clr
)
373 stack
[pos
++] = ab_tail
[code
];
374 code
= ab_prefix
[code
];
376 stack
[pos
] = code
; /* push last code into the stack */
377 abcabca
= code
; /* save for special case */
379 /* make new entry in alphabet (only if NOT just cleared) */
382 ab_prefix
[ab_free
] = lastcode
;
383 ab_tail
[ab_free
] = code
;
386 if ((ab_free
> ab_max
) && (ab_bits
< 12))
389 ab_max
= (1 << ab_bits
) - 1;
393 /* dump stack data to the buffer */
396 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
404 /* support for interlaced images */
407 case 1: y
+= 8; break;
408 case 2: y
+= 8; break;
409 case 3: y
+= 4; break;
410 case 4: y
+= 2; break;
416 case 2: y
= 4; break;
417 case 3: y
= 2; break;
418 case 4: y
= 1; break;
433 while (code
!= ab_fin
);
440 // Reads and decodes one or more GIF images, depending on whether
441 // animated GIF support is enabled. Can read GIFs with any bit
442 // size (color depth), but the output images are always expanded
443 // to 8 bits per pixel. Also, the image palettes always contain
444 // 256 colors, although some of them may be unused. Returns E_OK
445 // (== 0) on success, or an error code if something fails. Error
446 // codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see header file).
448 int wxGIFDecoder::ReadGIF()
450 int ncolors
, bits
, interl
, transparent
, disposal
, i
;
454 unsigned char pal
[768];
455 unsigned char buf
[16];
456 IMAGEN
**ppimg
, *pimg
, *pprev
;
459 /* check GIF signature and animated GIF support (ver. >= 89a) */
462 if (memcmp(buf
, "GIF", 3) != 0)
465 if (memcmp(buf
+ 3, "89a", 3) < 0)
468 /* read logical screen descriptor block (LSDB) */
470 m_screenw
= buf
[0] + 256 * buf
[1];
471 m_screenh
= buf
[2] + 256 * buf
[3];
473 /* load global color map if available */
474 if ((buf
[4] & 0x80) == 0x80)
476 m_background
= buf
[5];
478 ncolors
= 2 << (buf
[4] & 0x07);
479 m_f
->Read(pal
, 3 * ncolors
);
482 /* transparent colour, disposal method and delay default to unused */
494 type
= (unsigned char)m_f
->GetC();
500 /* extension block? */
503 if (((unsigned char)m_f
->GetC()) == 0xF9)
504 /* graphics control extension, parse it */
508 /* read delay and convert from 1/100 of a second to ms */
509 delay
= 10 * (buf
[2] + 256 * buf
[3]);
511 /* read transparent colour index, if used */
513 transparent
= buf
[4];
515 /* read disposal method */
516 disposal
= (buf
[1] & 0x1C) - 1;
519 /* other extension, skip */
521 while ((i
= (unsigned char)m_f
->GetC()) != 0)
523 /* This line should not be neccessary!
524 * Some images are not loaded correctly
525 * without it. A bug in wxStream?
527 // m_f->SeekI(m_f->TellI(), wxFromStart);
528 m_f
->SeekI(i
, wxFromCurrent
);
533 /* image descriptor block? */
536 /* allocate memory for IMAGEN struct */
537 pimg
= (*ppimg
) = (IMAGEN
*) malloc(sizeof(IMAGEN
));
545 /* fill in the data */
547 pimg
->left
= buf
[4] + 256 * buf
[5];
548 pimg
->top
= buf
[4] + 256 * buf
[5];
549 pimg
->w
= buf
[4] + 256 * buf
[5];
550 pimg
->h
= buf
[6] + 256 * buf
[7];
551 interl
= ((buf
[8] & 0x40)? 1 : 0);
552 size
= pimg
->w
* pimg
->h
;
554 pimg
->transparent
= transparent
;
555 pimg
->disposal
= disposal
;
562 /* allocate memory for image and palette */
563 pimg
->p
= (unsigned char *) malloc(size
);
564 pimg
->pal
= (unsigned char *) malloc(768);
566 if ((!pimg
->p
) || (!pimg
->pal
))
572 /* load local color map if available, else use global map */
573 if ((buf
[8] & 0x80) == 0x80)
575 ncolors
= 2 << (buf
[8] & 0x07);
576 m_f
->Read(pimg
->pal
, 3 * ncolors
);
579 memcpy(pimg
->pal
, pal
, 768);
581 /* get initial code size from first byte in raster data */
582 bits
= (unsigned char)m_f
->GetC();
585 dgif(pimg
, interl
, bits
);
590 /* if we have one image and no animated GIF support, exit */
591 if (m_nimages
== 1 && !m_anim
)
595 /* finish successfully :-) */
606 #endif // wxUSE_STREAM