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