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