]> git.saurik.com Git - wxWidgets.git/blame - src/common/gifdecod.cpp
clipboard update and latest module definition file of .dll build
[wxWidgets.git] / src / common / gifdecod.cpp
CommitLineData
464122b6
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: gifdecod.cpp
3// Purpose: wxGIFDecoder, GIF reader for wxImage and wxAnimation
4// Author: Guillermo Rodriguez Garcia <guille@iies.es>
9d0e21da
GRG
5// Version: 3.04
6// RCS-ID: $Id$
464122b6
JS
7// Copyright: (c) Guillermo Rodriguez Garcia
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "gifdecod.h"
13#endif
14
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19# pragma hdrstop
20#endif
21
22#ifndef WX_PRECOMP
7be110e3 23# include "wx/defs.h"
464122b6
JS
24#endif
25
7be110e3 26#if wxUSE_STREAMS && wxUSE_GIF
464122b6
JS
27
28#include <stdlib.h>
29#include <string.h>
464122b6 30#include "wx/gifdecod.h"
2ce0a6e2 31
464122b6
JS
32
33//---------------------------------------------------------------------------
34// wxGIFDecoder constructor and destructor
35//---------------------------------------------------------------------------
36
37wxGIFDecoder::wxGIFDecoder(wxInputStream *s, bool anim)
38{
9742d3cc 39 m_f = s;
464122b6
JS
40 m_anim = anim;
41
42 m_background = -1;
43 m_screenw = 0;
44 m_screenh = 0;
45
46 m_pimage = NULL;
47 m_pfirst = NULL;
48 m_plast = NULL;
49 m_image = 0;
50 m_nimages = 0;
51}
52
53wxGIFDecoder::~wxGIFDecoder()
54{
55 Destroy();
56}
57
58void wxGIFDecoder::Destroy()
59{
e4b8154a 60 GIFImage *pimg, *paux;
464122b6
JS
61
62 pimg = m_pfirst;
63
64 while (pimg != NULL)
65 {
b11e8fb6
VZ
66 paux = pimg->next;
67 free(pimg->p);
68 free(pimg->pal);
69 delete pimg;
70 pimg = paux;
464122b6 71 }
9742d3cc
GRG
72
73 m_pimage = NULL;
74 m_pfirst = NULL;
75 m_plast = NULL;
76 m_image = 0;
77 m_nimages = 0;
464122b6
JS
78}
79
80
81//---------------------------------------------------------------------------
82// Convert this image to a wxImage object
83//---------------------------------------------------------------------------
84
85// This function was designed by Vaclav Slavik
86
87bool wxGIFDecoder::ConvertToImage(wxImage *image) const
88{
89 unsigned char *src, *dst, *pal;
90 unsigned long i;
91 int transparent;
92
3c87527e
GRG
93 /* just in case... */
94 image->Destroy();
95
464122b6
JS
96 /* create the image */
97 image->Create(GetWidth(), GetHeight());
98
99 if (!image->Ok())
b11e8fb6 100 return FALSE;
464122b6
JS
101
102 pal = GetPalette();
103 src = GetData();
104 dst = image->GetData();
105 transparent = GetTransparentColour();
106
107 /* set transparent colour mask */
108 if (transparent != -1)
109 {
b11e8fb6
VZ
110 for (i = 0; i < 256; i++)
111 {
112 if ((pal[3 * i + 0] == 255) &&
113 (pal[3 * i + 1] == 0) &&
114 (pal[3 * i + 2] == 255))
115 {
116 pal[3 * i + 2] = 254;
117 }
118 }
119
120 pal[3 * transparent + 0] = 255,
121 pal[3 * transparent + 1] = 0,
122 pal[3 * transparent + 2] = 255;
123
124 image->SetMaskColour(255, 0, 255);
464122b6
JS
125 }
126 else
b11e8fb6 127 image->SetMask(FALSE);
464122b6 128
b11e8fb6 129#if wxUSE_PALETTE
3f4fc796
JS
130 if (pal)
131 {
b11e8fb6
VZ
132 unsigned char r[256];
133 unsigned char g[256];
134 unsigned char b[256];
135
136 for (i = 0; i < 256; i++)
137 {
138 r[i] = pal[3*i + 0];
139 g[i] = pal[3*i + 1];
140 b[i] = pal[3*i + 2];
141 }
142
143 image->SetPalette(wxPalette(256, r, g, b));
3f4fc796 144 }
b11e8fb6 145#endif // wxUSE_PALETTE
3f4fc796 146
464122b6
JS
147 /* copy image data */
148 for (i = 0; i < (GetWidth() * GetHeight()); i++, src++)
149 {
b11e8fb6
VZ
150 *(dst++) = pal[3 * (*src) + 0];
151 *(dst++) = pal[3 * (*src) + 1];
152 *(dst++) = pal[3 * (*src) + 2];
464122b6
JS
153 }
154
155 return TRUE;
156}
157
2ce0a6e2 158
464122b6
JS
159//---------------------------------------------------------------------------
160// Data accessors
161//---------------------------------------------------------------------------
162
163// Get data for current frame
164
165int wxGIFDecoder::GetFrameIndex() const { return m_image; }
166unsigned char* wxGIFDecoder::GetData() const { return (m_pimage->p); }
167unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage->pal); }
168unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage->w); }
169unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage->h); }
170unsigned int wxGIFDecoder::GetTop() const { return (m_pimage->top); }
171unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage->left); }
172int wxGIFDecoder::GetTransparentColour() const { return (m_pimage->transparent); }
173int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage->disposal); }
174long wxGIFDecoder::GetDelay() const { return (m_pimage->delay); }
175
176// Get global data
177
178unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw; }
179unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh; }
180int wxGIFDecoder::GetBackgroundColour() const { return m_background; }
181int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages; }
182bool wxGIFDecoder::IsAnimation() const { return (m_nimages > 1); }
183
184
185//---------------------------------------------------------------------------
186// Functions to move through the animation
187//---------------------------------------------------------------------------
188
189bool wxGIFDecoder::GoFirstFrame()
190{
191 if (!IsAnimation())
b11e8fb6 192 return FALSE;
464122b6
JS
193
194 m_image = 1;
195 m_pimage = m_pfirst;
196 return TRUE;
197}
198
199bool wxGIFDecoder::GoLastFrame()
200{
201 if (!IsAnimation())
b11e8fb6 202 return FALSE;
464122b6
JS
203
204 m_image = m_nimages;
205 m_pimage = m_plast;
206 return TRUE;
207}
208
209bool wxGIFDecoder::GoNextFrame(bool cyclic)
210{
211 if (!IsAnimation())
b11e8fb6 212 return FALSE;
464122b6
JS
213
214 if ((m_image < m_nimages) || (cyclic))
215 {
b11e8fb6
VZ
216 m_pimage = m_pimage->next;
217 m_image++;
464122b6 218
b11e8fb6
VZ
219 if (!m_pimage)
220 {
221 m_image = 1;
222 m_pimage = m_pfirst;
223 }
464122b6 224
b11e8fb6 225 return TRUE;
464122b6
JS
226 }
227 else
b11e8fb6 228 return FALSE;
2ce0a6e2 229}
464122b6
JS
230
231bool wxGIFDecoder::GoPrevFrame(bool cyclic)
232{
233 if (!IsAnimation())
b11e8fb6 234 return FALSE;
464122b6
JS
235
236 if ((m_image > 1) || (cyclic))
237 {
b11e8fb6
VZ
238 m_pimage = m_pimage->prev;
239 m_image--;
464122b6 240
b11e8fb6
VZ
241 if (!m_pimage)
242 {
243 m_image = m_nimages;
244 m_pimage = m_plast;
245 }
464122b6 246
b11e8fb6 247 return TRUE;
464122b6
JS
248 }
249 else
b11e8fb6 250 return FALSE;
464122b6
JS
251}
252
253bool wxGIFDecoder::GoFrame(int which)
254{
255 int i;
256
257 if (!IsAnimation())
b11e8fb6 258 return FALSE;
464122b6
JS
259
260 if ((which >= 1) && (which <= m_nimages))
261 {
b11e8fb6 262 m_pimage = m_pfirst;
464122b6 263
b11e8fb6
VZ
264 for (i = 1; i < which; i++)
265 m_pimage = m_pimage->next;
464122b6 266
b11e8fb6 267 return TRUE;
464122b6
JS
268 }
269 else
b11e8fb6 270 return FALSE;
464122b6
JS
271}
272
273
274//---------------------------------------------------------------------------
275// GIF reading and decoding
276//---------------------------------------------------------------------------
277
278// getcode:
279// Reads the next code from the file stream, with size 'bits'
280//
281int wxGIFDecoder::getcode(int bits, int ab_fin)
282{
283 unsigned int mask; /* bit mask */
284 unsigned int code; /* code (result) */
285
286
287 /* get remaining bits from last byte read */
288 mask = (1 << bits) - 1;
289 code = (m_lastbyte >> (8 - m_restbits)) & mask;
290
291 /* keep reading new bytes while needed */
292 while (bits > m_restbits)
293 {
b11e8fb6
VZ
294 /* if no bytes left in this block, read the next block */
295 if (m_restbyte == 0)
296 {
297 m_restbyte = (unsigned char)m_f->GetC();
298
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.
303 */
304 if (m_restbyte == 0)
305 {
306 code = ab_fin;
307 break;
308 }
309
310 /* prefetch data */
311 m_f->Read((void *) m_buffer, m_restbyte);
312 m_bufp = m_buffer;
313 }
314
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);
319 m_restbyte--;
320
321 /* adjust total number of bits extracted from the buffer */
322 m_restbits = m_restbits + 8;
464122b6 323 }
2ce0a6e2 324
464122b6
JS
325 /* find number of bits remaining for next code */
326 m_restbits = (m_restbits - bits);
327
328 return code;
329}
330
331
332// dgif:
333// GIF decoding function. The initial code size (aka root size)
334// is 'bits'. Supports interlaced images (interl == 1).
335//
e4b8154a 336int wxGIFDecoder::dgif(GIFImage *img, int interl, int bits)
464122b6 337{
7679ac63
GRG
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 */
464122b6
JS
349
350 int code, readcode, lastcode, abcabca;
351
352 /* these won't change */
353 ab_clr = (1 << bits);
354 ab_fin = (1 << bits) + 1;
355
356 /* these will change through the decompression proccess */
357 ab_bits = bits + 1;
358 ab_free = (1 << bits) + 2;
359 ab_max = (1 << ab_bits) - 1;
360 lastcode = -1;
361 abcabca = -1;
362 pass = 1;
363 pos = x = y = 0;
364
8708a10f 365 /* reset decoder vars */
464122b6
JS
366 m_restbits = 0;
367 m_restbyte = 0;
368 m_lastbyte = 0;
369
370 do
371 {
b11e8fb6
VZ
372 /* get next code */
373 readcode = code = getcode(ab_bits, ab_fin);
374
375 /* end of image? */
376 if (code == ab_fin) break;
377
378 /* reset alphabet? */
379 if (code == ab_clr)
380 {
381 /* reset main variables */
382 ab_bits = bits + 1;
383 ab_free = (1 << bits) + 2;
384 ab_max = (1 << ab_bits) - 1;
385 lastcode = -1;
386 abcabca = -1;
387
388 /* skip to next code */
389 continue;
390 }
391
392 /* unknown code: special case (like in ABCABCA) */
393 if (code >= ab_free)
394 {
395 code = lastcode; /* take last string */
396 stack[pos++] = abcabca; /* add first character */
397 }
398
399 /* build the string for this code in the stack */
400 while (code > ab_clr)
401 {
402 stack[pos++] = ab_tail[code];
403 code = ab_prefix[code];
404 }
405 stack[pos] = code; /* push last code into the stack */
406 abcabca = code; /* save for special case */
407
408 /* make new entry in alphabet (only if NOT just cleared) */
409 if (lastcode != -1)
410 {
411 ab_prefix[ab_free] = lastcode;
412 ab_tail[ab_free] = code;
413 ab_free++;
414
415 if ((ab_free > ab_max) && (ab_bits < 12))
416 {
417 ab_bits++;
418 ab_max = (1 << ab_bits) - 1;
419 }
420 }
421
422 /* dump stack data to the buffer */
423 while (pos >= 0)
424 {
425 (img->p)[x + (y * (img->w))] = (char)stack[pos--];
426
427 if (++x >= (img->w))
428 {
429 x = 0;
430
431 if (interl)
432 {
433 /* support for interlaced images */
434 switch (pass)
435 {
436 case 1: y += 8; break;
437 case 2: y += 8; break;
438 case 3: y += 4; break;
439 case 4: y += 2; break;
440 }
441 if (y >= (img->h))
442 {
443 switch (++pass)
444 {
445 case 2: y = 4; break;
446 case 3: y = 2; break;
447 case 4: y = 1; break;
448 }
449 }
450 }
451 else
452 {
453 /* non-interlaced */
454 y++;
6363699a
VZ
455/*
456Normally image decoding is finished when an End of Information code is
457encountered (code == ab_fin) however some broken encoders write wrong
458"block byte counts" (The first byte value after the "code size" byte),
459being one value too high. It might very well be possible other variants
460of this problem occur as well. The only sensible solution seems to
461be to check for clipping.
462Example of wrong encoding:
463(1 * 1 B/W image, raster data stream follows in hex bytes)
464
46502 << B/W images have a code size of 2
46602 << Block byte count
46744 << LZW packed
46800 << Zero byte count (terminates data stream)
469
470Because the block byte count is 2, the zero byte count is used in the
471decoding process, and decoding is continued after this byte. (While it
472should signal an end of image)
473
474It should be:
47502
47602
47744
47801 << When decoded this correctly includes the End of Information code
47900
480
481Or (Worse solution):
48202
48301
48444
48500
486(The 44 doesn't include an End of Information code, but at least the
487decoder correctly skips to 00 now after decoding, and signals this
488as an End of Information itself)
489*/
490 if (y >= img->h)
491 {
492 code = ab_fin;
493 break;
494 }
b11e8fb6
VZ
495 }
496 }
497 }
498
499 pos = 0;
500 lastcode = readcode;
464122b6
JS
501 }
502 while (code != ab_fin);
503
33ac7e6f
KB
504 delete [] ab_prefix ;
505 delete [] ab_tail ;
506 delete [] stack ;
7679ac63 507
464122b6
JS
508 return 0;
509}
510
511
3c87527e
GRG
512// CanRead:
513// Returns TRUE if the file looks like a valid GIF, FALSE otherwise.
514//
515bool wxGIFDecoder::CanRead()
516{
517 unsigned char buf[3];
518
3c87527e 519 m_f->Read(buf, 3);
700ec454 520 m_f->SeekI(-3, wxFromCurrent);
3c87527e
GRG
521
522 return (memcmp(buf, "GIF", 3) == 0);
523}
524
525
464122b6
JS
526// ReadGIF:
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
8141573c 531// 256 colors, although some of them may be unused. Returns wxGIF_OK
e4b8154a
GRG
532// (== 0) on success, or an error code if something fails (see
533// header file for details)
464122b6
JS
534//
535int wxGIFDecoder::ReadGIF()
536{
537 int ncolors, bits, interl, transparent, disposal, i;
538 long size;
539 long delay;
3ca6a5f0 540 unsigned char type = 0;
464122b6
JS
541 unsigned char pal[768];
542 unsigned char buf[16];
33ac7e6f 543 GIFImage **ppimg;
b11e8fb6 544 GIFImage *pimg, *pprev;
464122b6 545
3c87527e
GRG
546 /* check GIF signature */
547 if (!CanRead())
b11e8fb6 548 return wxGIF_INVFORMAT;
464122b6 549
8141573c 550 /* check for animated GIF support (ver. >= 89a) */
464122b6
JS
551 m_f->Read(buf, 6);
552
464122b6 553 if (memcmp(buf + 3, "89a", 3) < 0)
b11e8fb6 554 m_anim = FALSE;
464122b6
JS
555
556 /* read logical screen descriptor block (LSDB) */
557 m_f->Read(buf, 7);
558 m_screenw = buf[0] + 256 * buf[1];
559 m_screenh = buf[2] + 256 * buf[3];
560
561 /* load global color map if available */
562 if ((buf[4] & 0x80) == 0x80)
563 {
b11e8fb6 564 m_background = buf[5];
464122b6 565
b11e8fb6
VZ
566 ncolors = 2 << (buf[4] & 0x07);
567 m_f->Read(pal, 3 * ncolors);
464122b6
JS
568 }
569
570 /* transparent colour, disposal method and delay default to unused */
571 transparent = -1;
572 disposal = -1;
573 delay = -1;
574
575 /* read images */
576 ppimg = &m_pfirst;
577 pprev = NULL;
578 pimg = NULL;
579
8141573c
GRG
580 bool done = FALSE;
581
582 while(!done)
464122b6 583 {
b11e8fb6
VZ
584 type = (unsigned char)m_f->GetC();
585
586 /* end of data? */
587 if (type == 0x3B)
588 {
589 done = TRUE;
590 }
591 else
592 /* extension block? */
593 if (type == 0x21)
594 {
595 if (((unsigned char)m_f->GetC()) == 0xF9)
596 /* graphics control extension, parse it */
597 {
598 m_f->Read(buf, 6);
599
600 /* read delay and convert from 1/100 of a second to ms */
601 delay = 10 * (buf[2] + 256 * buf[3]);
602
603 /* read transparent colour index, if used */
604 if (buf[1] & 0x01)
605 transparent = buf[4];
606
607 /* read disposal method */
608 disposal = (buf[1] & 0x1C) - 1;
609 }
610 else
611 /* other extension, skip */
612 {
613 while ((i = (unsigned char)m_f->GetC()) != 0)
614 {
615 m_f->SeekI(i, wxFromCurrent);
616 }
617 }
618 }
619 else
620 /* image descriptor block? */
621 if (type == 0x2C)
622 {
623 /* allocate memory for IMAGEN struct */
624 pimg = (*ppimg) = new GIFImage();
625
626 if (pimg == NULL)
627 {
628 Destroy();
629 return wxGIF_MEMERR;
630 }
631
632 /* fill in the data */
633 m_f->Read(buf, 9);
634 pimg->left = buf[0] + 256 * buf[1];
635 pimg->top = buf[2] + 256 * buf[3];
bd52bee1 636/*
b11e8fb6
VZ
637 pimg->left = buf[4] + 256 * buf[5];
638 pimg->top = buf[4] + 256 * buf[5];
bd52bee1 639*/
b11e8fb6
VZ
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;
644
645 pimg->transparent = transparent;
646 pimg->disposal = disposal;
647 pimg->delay = delay;
648 pimg->next = NULL;
649 pimg->prev = pprev;
650 pprev = pimg;
651 ppimg = &pimg->next;
652
653 /* allocate memory for image and palette */
654 pimg->p = (unsigned char *) malloc((size_t)size);
655 pimg->pal = (unsigned char *) malloc(768);
656
657 if ((!pimg->p) || (!pimg->pal))
658 {
659 Destroy();
660 return wxGIF_MEMERR;
661 }
662
663 /* load local color map if available, else use global map */
664 if ((buf[8] & 0x80) == 0x80)
665 {
666 ncolors = 2 << (buf[8] & 0x07);
667 m_f->Read(pimg->pal, 3 * ncolors);
668 }
669 else
670 memcpy(pimg->pal, pal, 768);
671
672 /* get initial code size from first byte in raster data */
673 bits = (unsigned char)m_f->GetC();
674
675 /* decode image */
676 dgif(pimg, interl, bits);
677 m_nimages++;
678
679 /* if this is not an animated GIF, exit after first image */
680 if (!m_anim)
681 done = TRUE;
682 }
464122b6
JS
683 }
684
8141573c 685 /* setup image pointers */
464122b6
JS
686 if (m_nimages != 0)
687 {
b11e8fb6
VZ
688 m_image = 1;
689 m_plast = pimg;
690 m_pimage = m_pfirst;
464122b6
JS
691 }
692
8141573c
GRG
693 /* try to read to the end of the stream */
694 while (type != 0x3B)
695 {
ef3a5e0a
VS
696 if (!m_f->IsOk())
697 return wxGIF_TRUNCATED;
698
b11e8fb6
VZ
699 type = (unsigned char)m_f->GetC();
700
701 if (type == 0x21)
702 {
703 /* extension type */
704 (void) m_f->GetC();
705
706 /* skip all data */
707 while ((i = (unsigned char)m_f->GetC()) != 0)
708 {
709 m_f->SeekI(i, wxFromCurrent);
710 }
711 }
712 else if (type == 0x2C)
713 {
714 /* image descriptor block */
715 m_f->Read(buf, 9);
716
717 /* local color map */
718 if ((buf[8] & 0x80) == 0x80)
719 {
720 ncolors = 2 << (buf[8] & 0x07);
721 m_f->SeekI(3 * ncolors, wxFromCurrent);
722 }
723
724 /* initial code size */
725 (void) m_f->GetC();
726
727 /* skip all data */
728 while ((i = (unsigned char)m_f->GetC()) != 0)
729 {
730 m_f->SeekI(i, wxFromCurrent);
731 }
732 }
733 else if ((type != 0x3B) && (type != 00)) /* testing */
734 {
735 /* images are OK, but couldn't read to the end of the stream */
736 return wxGIF_TRUNCATED;
737 }
8141573c
GRG
738 }
739
e4b8154a 740 return wxGIF_OK;
464122b6
JS
741}
742
7be110e3 743#endif // wxUSE_STREAMS && wxUSE_GIF