]> git.saurik.com Git - wxWidgets.git/blame - src/common/gifdecod.cpp
Rich text lib separation.
[wxWidgets.git] / src / common / gifdecod.cpp
CommitLineData
464122b6 1/////////////////////////////////////////////////////////////////////////////
8898456d 2// Name: src/common/gifdecod.cpp
464122b6
JS
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 7// Copyright: (c) Guillermo Rodriguez Garcia
65571936 8// Licence: wxWindows licence
464122b6
JS
9/////////////////////////////////////////////////////////////////////////////
10
464122b6
JS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
8898456d 15 #pragma hdrstop
464122b6
JS
16#endif
17
8898456d
WS
18#if wxUSE_STREAMS && wxUSE_GIF
19
464122b6 20#ifndef WX_PRECOMP
8898456d 21 #include "wx/palette.h"
464122b6
JS
22#endif
23
464122b6
JS
24#include <stdlib.h>
25#include <string.h>
464122b6 26#include "wx/gifdecod.h"
2ce0a6e2 27
464122b6 28
65c36a73
VZ
29//---------------------------------------------------------------------------
30// GIFImage constructor
31//---------------------------------------------------------------------------
32GIFImage::GIFImage()
33{
34 w = 0;
35 h = 0;
36 left = 0;
37 top = 0;
38 transparent = 0;
39 disposal = 0;
40 delay = -1;
41 p = (unsigned char *) NULL;
42 pal = (unsigned char *) NULL;
43 next = (GIFImage *) NULL;
44 prev = (GIFImage *) NULL;
45}
46
464122b6
JS
47//---------------------------------------------------------------------------
48// wxGIFDecoder constructor and destructor
49//---------------------------------------------------------------------------
50
51wxGIFDecoder::wxGIFDecoder(wxInputStream *s, bool anim)
52{
9742d3cc 53 m_f = s;
464122b6
JS
54 m_anim = anim;
55
56 m_background = -1;
57 m_screenw = 0;
58 m_screenh = 0;
59
60 m_pimage = NULL;
61 m_pfirst = NULL;
62 m_plast = NULL;
63 m_image = 0;
64 m_nimages = 0;
65}
66
67wxGIFDecoder::~wxGIFDecoder()
68{
69 Destroy();
70}
71
72void wxGIFDecoder::Destroy()
73{
e4b8154a 74 GIFImage *pimg, *paux;
464122b6
JS
75
76 pimg = m_pfirst;
77
78 while (pimg != NULL)
79 {
b11e8fb6
VZ
80 paux = pimg->next;
81 free(pimg->p);
82 free(pimg->pal);
83 delete pimg;
84 pimg = paux;
464122b6 85 }
9742d3cc
GRG
86
87 m_pimage = NULL;
88 m_pfirst = NULL;
89 m_plast = NULL;
90 m_image = 0;
91 m_nimages = 0;
464122b6
JS
92}
93
94
95//---------------------------------------------------------------------------
96// Convert this image to a wxImage object
97//---------------------------------------------------------------------------
98
99// This function was designed by Vaclav Slavik
100
101bool wxGIFDecoder::ConvertToImage(wxImage *image) const
102{
103 unsigned char *src, *dst, *pal;
104 unsigned long i;
105 int transparent;
106
3c87527e
GRG
107 /* just in case... */
108 image->Destroy();
109
464122b6
JS
110 /* create the image */
111 image->Create(GetWidth(), GetHeight());
112
113 if (!image->Ok())
5d3e7b52 114 return false;
464122b6
JS
115
116 pal = GetPalette();
117 src = GetData();
118 dst = image->GetData();
119 transparent = GetTransparentColour();
120
121 /* set transparent colour mask */
122 if (transparent != -1)
123 {
b11e8fb6
VZ
124 for (i = 0; i < 256; i++)
125 {
126 if ((pal[3 * i + 0] == 255) &&
127 (pal[3 * i + 1] == 0) &&
128 (pal[3 * i + 2] == 255))
129 {
130 pal[3 * i + 2] = 254;
131 }
132 }
133
134 pal[3 * transparent + 0] = 255,
135 pal[3 * transparent + 1] = 0,
136 pal[3 * transparent + 2] = 255;
137
138 image->SetMaskColour(255, 0, 255);
464122b6
JS
139 }
140 else
5d3e7b52 141 image->SetMask(false);
464122b6 142
b11e8fb6 143#if wxUSE_PALETTE
fbf1ee1d
VZ
144 unsigned char r[256];
145 unsigned char g[256];
146 unsigned char b[256];
b11e8fb6 147
fbf1ee1d
VZ
148 for (i = 0; i < 256; i++)
149 {
150 r[i] = pal[3*i + 0];
151 g[i] = pal[3*i + 1];
152 b[i] = pal[3*i + 2];
3f4fc796 153 }
fbf1ee1d
VZ
154
155 image->SetPalette(wxPalette(256, r, g, b));
b11e8fb6 156#endif // wxUSE_PALETTE
3f4fc796 157
464122b6
JS
158 /* copy image data */
159 for (i = 0; i < (GetWidth() * GetHeight()); i++, src++)
160 {
b11e8fb6
VZ
161 *(dst++) = pal[3 * (*src) + 0];
162 *(dst++) = pal[3 * (*src) + 1];
163 *(dst++) = pal[3 * (*src) + 2];
464122b6
JS
164 }
165
5d3e7b52 166 return true;
464122b6
JS
167}
168
2ce0a6e2 169
464122b6
JS
170//---------------------------------------------------------------------------
171// Data accessors
172//---------------------------------------------------------------------------
173
174// Get data for current frame
175
176int wxGIFDecoder::GetFrameIndex() const { return m_image; }
177unsigned char* wxGIFDecoder::GetData() const { return (m_pimage->p); }
178unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage->pal); }
179unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage->w); }
180unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage->h); }
181unsigned int wxGIFDecoder::GetTop() const { return (m_pimage->top); }
182unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage->left); }
183int wxGIFDecoder::GetTransparentColour() const { return (m_pimage->transparent); }
184int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage->disposal); }
185long wxGIFDecoder::GetDelay() const { return (m_pimage->delay); }
186
187// Get global data
188
189unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw; }
190unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh; }
191int wxGIFDecoder::GetBackgroundColour() const { return m_background; }
192int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages; }
193bool wxGIFDecoder::IsAnimation() const { return (m_nimages > 1); }
194
195
196//---------------------------------------------------------------------------
197// Functions to move through the animation
198//---------------------------------------------------------------------------
199
200bool wxGIFDecoder::GoFirstFrame()
201{
202 if (!IsAnimation())
5d3e7b52 203 return false;
464122b6
JS
204
205 m_image = 1;
206 m_pimage = m_pfirst;
5d3e7b52 207 return true;
464122b6
JS
208}
209
210bool wxGIFDecoder::GoLastFrame()
211{
212 if (!IsAnimation())
5d3e7b52 213 return false;
464122b6
JS
214
215 m_image = m_nimages;
216 m_pimage = m_plast;
5d3e7b52 217 return true;
464122b6
JS
218}
219
220bool wxGIFDecoder::GoNextFrame(bool cyclic)
221{
222 if (!IsAnimation())
5d3e7b52 223 return false;
464122b6
JS
224
225 if ((m_image < m_nimages) || (cyclic))
226 {
b11e8fb6
VZ
227 m_pimage = m_pimage->next;
228 m_image++;
464122b6 229
b11e8fb6
VZ
230 if (!m_pimage)
231 {
232 m_image = 1;
233 m_pimage = m_pfirst;
234 }
464122b6 235
5d3e7b52 236 return true;
464122b6
JS
237 }
238 else
5d3e7b52 239 return false;
2ce0a6e2 240}
464122b6
JS
241
242bool wxGIFDecoder::GoPrevFrame(bool cyclic)
243{
244 if (!IsAnimation())
5d3e7b52 245 return false;
464122b6
JS
246
247 if ((m_image > 1) || (cyclic))
248 {
b11e8fb6
VZ
249 m_pimage = m_pimage->prev;
250 m_image--;
464122b6 251
b11e8fb6
VZ
252 if (!m_pimage)
253 {
254 m_image = m_nimages;
255 m_pimage = m_plast;
256 }
464122b6 257
5d3e7b52 258 return true;
464122b6
JS
259 }
260 else
5d3e7b52 261 return false;
464122b6
JS
262}
263
264bool wxGIFDecoder::GoFrame(int which)
265{
464122b6 266 if (!IsAnimation())
5d3e7b52 267 return false;
464122b6
JS
268
269 if ((which >= 1) && (which <= m_nimages))
270 {
6b5403c8 271 m_image = 1;
b11e8fb6 272 m_pimage = m_pfirst;
464122b6 273
6b5403c8
VZ
274 while (m_image < which)
275 {
276 m_image++;
b11e8fb6 277 m_pimage = m_pimage->next;
6b5403c8 278 }
464122b6 279
5d3e7b52 280 return true;
464122b6
JS
281 }
282 else
5d3e7b52 283 return false;
464122b6
JS
284}
285
286
287//---------------------------------------------------------------------------
288// GIF reading and decoding
289//---------------------------------------------------------------------------
290
291// getcode:
292// Reads the next code from the file stream, with size 'bits'
293//
294int wxGIFDecoder::getcode(int bits, int ab_fin)
295{
296 unsigned int mask; /* bit mask */
297 unsigned int code; /* code (result) */
298
299
300 /* get remaining bits from last byte read */
301 mask = (1 << bits) - 1;
302 code = (m_lastbyte >> (8 - m_restbits)) & mask;
303
304 /* keep reading new bytes while needed */
305 while (bits > m_restbits)
306 {
b11e8fb6
VZ
307 /* if no bytes left in this block, read the next block */
308 if (m_restbyte == 0)
309 {
310 m_restbyte = (unsigned char)m_f->GetC();
311
312 /* Some encoders are a bit broken: instead of issuing
313 * an end-of-image symbol (ab_fin) they come up with
314 * a zero-length subblock!! We catch this here so
315 * that the decoder sees an ab_fin code.
316 */
317 if (m_restbyte == 0)
318 {
319 code = ab_fin;
320 break;
321 }
322
323 /* prefetch data */
324 m_f->Read((void *) m_buffer, m_restbyte);
65c36a73
VZ
325 if (m_f->LastRead() != m_restbyte)
326 {
327 code = ab_fin;
328 return code;
329 }
b11e8fb6
VZ
330 m_bufp = m_buffer;
331 }
332
333 /* read next byte and isolate the bits we need */
334 m_lastbyte = (unsigned char) (*m_bufp++);
335 mask = (1 << (bits - m_restbits)) - 1;
336 code = code + ((m_lastbyte & mask) << m_restbits);
337 m_restbyte--;
338
339 /* adjust total number of bits extracted from the buffer */
340 m_restbits = m_restbits + 8;
464122b6 341 }
2ce0a6e2 342
464122b6
JS
343 /* find number of bits remaining for next code */
344 m_restbits = (m_restbits - bits);
345
346 return code;
347}
348
349
350// dgif:
351// GIF decoding function. The initial code size (aka root size)
352// is 'bits'. Supports interlaced images (interl == 1).
65c36a73
VZ
353// Returns wxGIF_OK (== 0) on success, or an error code if something
354// fails (see header file for details)
e4b8154a 355int wxGIFDecoder::dgif(GIFImage *img, int interl, int bits)
464122b6 356{
65c36a73
VZ
357 static const int allocSize = 4096 + 1;
358 int *ab_prefix = new int[allocSize]; /* alphabet (prefixes) */
359 if (ab_prefix == NULL)
360 {
361 return wxGIF_MEMERR;
362 }
363
364 int *ab_tail = new int[allocSize]; /* alphabet (tails) */
365 if (ab_tail == NULL)
366 {
367 delete[] ab_prefix;
368 return wxGIF_MEMERR;
369 }
370
371 int *stack = new int[allocSize]; /* decompression stack */
372 if (stack == NULL)
373 {
374 delete[] ab_prefix;
375 delete[] ab_tail;
376 return wxGIF_MEMERR;
377 }
378
7679ac63
GRG
379 int ab_clr; /* clear code */
380 int ab_fin; /* end of info code */
381 int ab_bits; /* actual symbol width, in bits */
382 int ab_free; /* first free position in alphabet */
383 int ab_max; /* last possible character in alphabet */
384 int pass; /* pass number in interlaced images */
385 int pos; /* index into decompresion stack */
386 unsigned int x, y; /* position in image buffer */
464122b6
JS
387
388 int code, readcode, lastcode, abcabca;
389
390 /* these won't change */
391 ab_clr = (1 << bits);
392 ab_fin = (1 << bits) + 1;
393
394 /* these will change through the decompression proccess */
395 ab_bits = bits + 1;
396 ab_free = (1 << bits) + 2;
397 ab_max = (1 << ab_bits) - 1;
398 lastcode = -1;
399 abcabca = -1;
400 pass = 1;
401 pos = x = y = 0;
402
8708a10f 403 /* reset decoder vars */
464122b6
JS
404 m_restbits = 0;
405 m_restbyte = 0;
406 m_lastbyte = 0;
407
408 do
409 {
b11e8fb6
VZ
410 /* get next code */
411 readcode = code = getcode(ab_bits, ab_fin);
412
413 /* end of image? */
414 if (code == ab_fin) break;
415
416 /* reset alphabet? */
417 if (code == ab_clr)
418 {
419 /* reset main variables */
420 ab_bits = bits + 1;
421 ab_free = (1 << bits) + 2;
422 ab_max = (1 << ab_bits) - 1;
423 lastcode = -1;
424 abcabca = -1;
425
426 /* skip to next code */
427 continue;
428 }
429
430 /* unknown code: special case (like in ABCABCA) */
431 if (code >= ab_free)
432 {
433 code = lastcode; /* take last string */
434 stack[pos++] = abcabca; /* add first character */
435 }
436
437 /* build the string for this code in the stack */
438 while (code > ab_clr)
439 {
440 stack[pos++] = ab_tail[code];
441 code = ab_prefix[code];
65c36a73
VZ
442
443 // Don't overflow. This shouldn't happen with normal
444 // GIF files, the allocSize of 4096+1 is enough. This
445 // will only happen with badly formed GIFs.
446 if (pos >= allocSize)
447 {
448 delete[] ab_prefix;
449 delete[] ab_tail;
450 delete[] stack;
451 return wxGIF_INVFORMAT;
452 }
b11e8fb6 453 }
e34f4f19
VZ
454
455 if (pos >= allocSize)
456 {
457 delete[] ab_prefix;
458 delete[] ab_tail;
459 delete[] stack;
460 return wxGIF_INVFORMAT;
461 }
462
b11e8fb6
VZ
463 stack[pos] = code; /* push last code into the stack */
464 abcabca = code; /* save for special case */
465
466 /* make new entry in alphabet (only if NOT just cleared) */
467 if (lastcode != -1)
468 {
1819a5c1
VZ
469 // Normally, after the alphabet is full and can't grow any
470 // further (ab_free == 4096), encoder should (must?) emit CLEAR
471 // to reset it. This checks whether we really got it, otherwise
472 // the GIF is damaged.
473 if (ab_free > ab_max)
474 {
475 delete[] ab_prefix;
476 delete[] ab_tail;
477 delete[] stack;
478 return wxGIF_INVFORMAT;
479 }
480
481 // This assert seems unnecessary since the condition above
482 // eliminates the only case in which it went false. But I really
483 // don't like being forced to ask "Who in .text could have
484 // written there?!" And I wouldn't have been forced to ask if
485 // this line had already been here.
486 wxASSERT(ab_free < allocSize);
487
b11e8fb6
VZ
488 ab_prefix[ab_free] = lastcode;
489 ab_tail[ab_free] = code;
490 ab_free++;
491
492 if ((ab_free > ab_max) && (ab_bits < 12))
493 {
494 ab_bits++;
495 ab_max = (1 << ab_bits) - 1;
496 }
497 }
498
e34f4f19 499 /* dump stack data to the image buffer */
b11e8fb6
VZ
500 while (pos >= 0)
501 {
e34f4f19
VZ
502 (img->p)[x + (y * (img->w))] = (char) stack[pos];
503 pos--;
b11e8fb6
VZ
504
505 if (++x >= (img->w))
506 {
507 x = 0;
508
509 if (interl)
510 {
511 /* support for interlaced images */
512 switch (pass)
513 {
514 case 1: y += 8; break;
515 case 2: y += 8; break;
516 case 3: y += 4; break;
517 case 4: y += 2; break;
518 }
e34f4f19
VZ
519
520 /* loop until a valid y coordinate has been
521 found, Or if the maximum number of passes has
522 been reached, exit the loop, and stop image
3103e8a9 523 decoding (At this point the image is successfully
e34f4f19
VZ
524 decoded).
525 If we don't loop, but merely set y to some other
526 value, that new value might still be invalid depending
527 on the height of the image. This would cause out of
528 bounds writing.
529 */
530 while (y >= (img->h))
b11e8fb6
VZ
531 {
532 switch (++pass)
533 {
534 case 2: y = 4; break;
535 case 3: y = 2; break;
536 case 4: y = 1; break;
e34f4f19
VZ
537
538 default:
539 /*
540 It's possible we arrive here. For example this
541 happens when the image is interlaced, and the
542 height is 1. Looking at the above cases, the
543 lowest possible y is 1. While the only valid
544 one would be 0 for an image of height 1. So
545 'eventually' the loop will arrive here.
546 This case makes sure this while loop is
547 exited, as well as the 2 other ones.
548 */
549
550 // Set y to a valid coordinate so the local
551 // while loop will be exited. (y = 0 always
552 // is >= img->h since if img->h == 0 the
553 // image is never decoded)
554 y = 0;
555
556 // This will exit the other outer while loop
557 pos = -1;
558
559 // This will halt image decoding.
560 code = ab_fin;
561
562 break;
b11e8fb6
VZ
563 }
564 }
565 }
566 else
567 {
568 /* non-interlaced */
569 y++;
6363699a
VZ
570/*
571Normally image decoding is finished when an End of Information code is
572encountered (code == ab_fin) however some broken encoders write wrong
573"block byte counts" (The first byte value after the "code size" byte),
574being one value too high. It might very well be possible other variants
575of this problem occur as well. The only sensible solution seems to
576be to check for clipping.
577Example of wrong encoding:
578(1 * 1 B/W image, raster data stream follows in hex bytes)
579
58002 << B/W images have a code size of 2
58102 << Block byte count
58244 << LZW packed
58300 << Zero byte count (terminates data stream)
584
585Because the block byte count is 2, the zero byte count is used in the
586decoding process, and decoding is continued after this byte. (While it
587should signal an end of image)
588
589It should be:
59002
59102
59244
59301 << When decoded this correctly includes the End of Information code
59400
595
596Or (Worse solution):
59702
59801
59944
60000
601(The 44 doesn't include an End of Information code, but at least the
602decoder correctly skips to 00 now after decoding, and signals this
603as an End of Information itself)
604*/
605 if (y >= img->h)
606 {
607 code = ab_fin;
608 break;
609 }
b11e8fb6
VZ
610 }
611 }
612 }
613
614 pos = 0;
615 lastcode = readcode;
464122b6
JS
616 }
617 while (code != ab_fin);
618
33ac7e6f
KB
619 delete [] ab_prefix ;
620 delete [] ab_tail ;
621 delete [] stack ;
7679ac63 622
65c36a73 623 return wxGIF_OK;
464122b6
JS
624}
625
626
3c87527e 627// CanRead:
5d3e7b52 628// Returns true if the file looks like a valid GIF, false otherwise.
3c87527e
GRG
629//
630bool wxGIFDecoder::CanRead()
631{
632 unsigned char buf[3];
633
79fa2374 634 if ( !m_f->Read(buf, WXSIZEOF(buf)) )
5d3e7b52 635 return false;
79fa2374 636
30984dea 637 m_f->SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent);
3c87527e 638
79fa2374 639 return memcmp(buf, "GIF", WXSIZEOF(buf)) == 0;
3c87527e
GRG
640}
641
642
464122b6
JS
643// ReadGIF:
644// Reads and decodes one or more GIF images, depending on whether
645// animated GIF support is enabled. Can read GIFs with any bit
646// size (color depth), but the output images are always expanded
647// to 8 bits per pixel. Also, the image palettes always contain
8141573c 648// 256 colors, although some of them may be unused. Returns wxGIF_OK
e4b8154a
GRG
649// (== 0) on success, or an error code if something fails (see
650// header file for details)
464122b6
JS
651//
652int wxGIFDecoder::ReadGIF()
653{
65c36a73
VZ
654 unsigned int ncolors;
655 int bits, interl, transparent, disposal, i;
464122b6
JS
656 long size;
657 long delay;
3ca6a5f0 658 unsigned char type = 0;
464122b6
JS
659 unsigned char pal[768];
660 unsigned char buf[16];
33ac7e6f 661 GIFImage **ppimg;
65c36a73 662 GIFImage *pimg, *pprev;
464122b6 663
3c87527e
GRG
664 /* check GIF signature */
665 if (!CanRead())
b11e8fb6 666 return wxGIF_INVFORMAT;
464122b6 667
8141573c 668 /* check for animated GIF support (ver. >= 89a) */
65c36a73
VZ
669
670 static const size_t headerSize = (3 + 3);
671 m_f->Read(buf, headerSize);
672 if (m_f->LastRead() != headerSize)
673 {
674 return wxGIF_INVFORMAT;
675 }
464122b6 676
464122b6 677 if (memcmp(buf + 3, "89a", 3) < 0)
65c36a73 678 {
5d3e7b52 679 m_anim = false;
65c36a73 680 }
464122b6
JS
681
682 /* read logical screen descriptor block (LSDB) */
65c36a73
VZ
683 static const size_t lsdbSize = (2 + 2 + 1 + 1 + 1);
684 m_f->Read(buf, lsdbSize);
685 if (m_f->LastRead() != lsdbSize)
686 {
687 return wxGIF_INVFORMAT;
688 }
689
464122b6
JS
690 m_screenw = buf[0] + 256 * buf[1];
691 m_screenh = buf[2] + 256 * buf[3];
692
295dec28 693 if ((m_screenw == 0) || (m_screenh == 0))
525b0568
DS
694 {
695 return wxGIF_INVFORMAT;
696 }
697
464122b6
JS
698 /* load global color map if available */
699 if ((buf[4] & 0x80) == 0x80)
700 {
b11e8fb6 701 m_background = buf[5];
464122b6 702
b11e8fb6 703 ncolors = 2 << (buf[4] & 0x07);
65c36a73
VZ
704 size_t numBytes = 3 * ncolors;
705 m_f->Read(pal, numBytes);
706 if (m_f->LastRead() != numBytes)
707 {
708 return wxGIF_INVFORMAT;
709 }
464122b6
JS
710 }
711
712 /* transparent colour, disposal method and delay default to unused */
713 transparent = -1;
714 disposal = -1;
715 delay = -1;
716
717 /* read images */
718 ppimg = &m_pfirst;
719 pprev = NULL;
720 pimg = NULL;
721
5d3e7b52 722 bool done = false;
8141573c 723
525b0568 724 while (!done)
464122b6 725 {
b11e8fb6
VZ
726 type = (unsigned char)m_f->GetC();
727
65c36a73
VZ
728 /*
729 If the end of file has been reached (or an error) and a ";"
730 (0x3B) hasn't been encountered yet, exit the loop. (Without this
731 check the while loop would loop endlessly.) Later on, in the next while
732 loop, the file will be treated as being truncated (But still
733 be decoded as far as possible). returning wxGIF_TRUNCATED is not
734 possible here since some init code is done after this loop.
735 */
736 if (m_f->Eof())// || !m_f->IsOk())
737 {
738 /*
739 type is set to some bogus value, so there's no
740 need to continue evaluating it.
741 */
742 break; // Alternative : "return wxGIF_INVFORMAT;"
743 }
744
b11e8fb6
VZ
745 /* end of data? */
746 if (type == 0x3B)
747 {
5d3e7b52 748 done = true;
b11e8fb6
VZ
749 }
750 else
751 /* extension block? */
752 if (type == 0x21)
753 {
754 if (((unsigned char)m_f->GetC()) == 0xF9)
755 /* graphics control extension, parse it */
756 {
65c36a73
VZ
757 static const size_t gceSize = 6;
758 m_f->Read(buf, gceSize);
759 if (m_f->LastRead() != gceSize)
760 {
761 Destroy();
762 return wxGIF_INVFORMAT;
763 }
b11e8fb6
VZ
764
765 /* read delay and convert from 1/100 of a second to ms */
766 delay = 10 * (buf[2] + 256 * buf[3]);
767
768 /* read transparent colour index, if used */
769 if (buf[1] & 0x01)
770 transparent = buf[4];
771
772 /* read disposal method */
6b5403c8 773 disposal = ((buf[1] & 0x1C) >> 2) - 1;
b11e8fb6
VZ
774 }
775 else
776 /* other extension, skip */
777 {
778 while ((i = (unsigned char)m_f->GetC()) != 0)
779 {
780 m_f->SeekI(i, wxFromCurrent);
65c36a73
VZ
781 if (m_f->Eof())
782 {
5d3e7b52 783 done = true;
65c36a73
VZ
784 break;
785 }
b11e8fb6
VZ
786 }
787 }
788 }
789 else
790 /* image descriptor block? */
791 if (type == 0x2C)
792 {
793 /* allocate memory for IMAGEN struct */
794 pimg = (*ppimg) = new GIFImage();
795
796 if (pimg == NULL)
797 {
798 Destroy();
799 return wxGIF_MEMERR;
800 }
801
802 /* fill in the data */
65c36a73
VZ
803 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
804 m_f->Read(buf, idbSize);
805 if (m_f->LastRead() != idbSize)
806 {
807 Destroy();
808 return wxGIF_INVFORMAT;
809 }
810
b11e8fb6
VZ
811 pimg->left = buf[0] + 256 * buf[1];
812 pimg->top = buf[2] + 256 * buf[3];
bd52bee1 813/*
b11e8fb6
VZ
814 pimg->left = buf[4] + 256 * buf[5];
815 pimg->top = buf[4] + 256 * buf[5];
bd52bee1 816*/
b11e8fb6
VZ
817 pimg->w = buf[4] + 256 * buf[5];
818 pimg->h = buf[6] + 256 * buf[7];
65c36a73 819
295dec28 820 if ((pimg->w == 0) || (pimg->w > m_screenw) || (pimg->h == 0) || (pimg->h > m_screenh))
65c36a73
VZ
821 {
822 Destroy();
823 return wxGIF_INVFORMAT;
824 }
825
b11e8fb6
VZ
826 interl = ((buf[8] & 0x40)? 1 : 0);
827 size = pimg->w * pimg->h;
828
829 pimg->transparent = transparent;
830 pimg->disposal = disposal;
831 pimg->delay = delay;
832 pimg->next = NULL;
833 pimg->prev = pprev;
834 pprev = pimg;
835 ppimg = &pimg->next;
836
837 /* allocate memory for image and palette */
838 pimg->p = (unsigned char *) malloc((size_t)size);
839 pimg->pal = (unsigned char *) malloc(768);
840
841 if ((!pimg->p) || (!pimg->pal))
842 {
843 Destroy();
844 return wxGIF_MEMERR;
845 }
846
847 /* load local color map if available, else use global map */
848 if ((buf[8] & 0x80) == 0x80)
849 {
850 ncolors = 2 << (buf[8] & 0x07);
65c36a73 851 size_t numBytes = 3 * ncolors;
295dec28
DS
852 m_f->Read(pimg->pal, numBytes);
853 if (m_f->LastRead() != numBytes)
65c36a73
VZ
854 {
855 Destroy();
856 return wxGIF_INVFORMAT;
857 }
b11e8fb6
VZ
858 }
859 else
65c36a73 860 {
b11e8fb6 861 memcpy(pimg->pal, pal, 768);
65c36a73 862 }
b11e8fb6
VZ
863
864 /* get initial code size from first byte in raster data */
865 bits = (unsigned char)m_f->GetC();
525b0568
DS
866 if (bits == 0)
867 {
868 Destroy();
869 return wxGIF_INVFORMAT;
870 }
b11e8fb6
VZ
871
872 /* decode image */
65c36a73
VZ
873 int result = dgif(pimg, interl, bits);
874 if (result != wxGIF_OK)
875 {
876 Destroy();
877 return result;
878 }
b11e8fb6
VZ
879 m_nimages++;
880
881 /* if this is not an animated GIF, exit after first image */
882 if (!m_anim)
5d3e7b52 883 done = true;
b11e8fb6 884 }
464122b6
JS
885 }
886
525b0568 887 if (m_nimages <= 0)
464122b6 888 {
65c36a73
VZ
889 Destroy();
890 return wxGIF_INVFORMAT;
464122b6
JS
891 }
892
65c36a73
VZ
893 /* setup image pointers */
894 m_image = 1;
895 m_plast = pimg;
896 m_pimage = m_pfirst;
897
8141573c
GRG
898 /* try to read to the end of the stream */
899 while (type != 0x3B)
900 {
ef3a5e0a
VS
901 if (!m_f->IsOk())
902 return wxGIF_TRUNCATED;
65c36a73 903
b11e8fb6
VZ
904 type = (unsigned char)m_f->GetC();
905
906 if (type == 0x21)
907 {
908 /* extension type */
909 (void) m_f->GetC();
910
911 /* skip all data */
912 while ((i = (unsigned char)m_f->GetC()) != 0)
913 {
914 m_f->SeekI(i, wxFromCurrent);
915 }
916 }
917 else if (type == 0x2C)
918 {
919 /* image descriptor block */
65c36a73
VZ
920 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
921 m_f->Read(buf, idbSize);
922 if (m_f->LastRead() != idbSize)
923 {
924 Destroy();
925 return wxGIF_INVFORMAT;
926 }
b11e8fb6
VZ
927
928 /* local color map */
929 if ((buf[8] & 0x80) == 0x80)
930 {
931 ncolors = 2 << (buf[8] & 0x07);
7ac31c42
WS
932 wxFileOffset pos = m_f->TellI();
933 wxFileOffset numBytes = 3 * ncolors;
65c36a73
VZ
934 m_f->SeekI(numBytes, wxFromCurrent);
935 if (m_f->TellI() != (pos + numBytes))
936 {
937 Destroy();
938 return wxGIF_INVFORMAT;
939 }
b11e8fb6
VZ
940 }
941
942 /* initial code size */
943 (void) m_f->GetC();
944
945 /* skip all data */
946 while ((i = (unsigned char)m_f->GetC()) != 0)
947 {
948 m_f->SeekI(i, wxFromCurrent);
949 }
950 }
951 else if ((type != 0x3B) && (type != 00)) /* testing */
952 {
953 /* images are OK, but couldn't read to the end of the stream */
954 return wxGIF_TRUNCATED;
955 }
8141573c
GRG
956 }
957
e4b8154a 958 return wxGIF_OK;
464122b6
JS
959}
960
7be110e3 961#endif // wxUSE_STREAMS && wxUSE_GIF