]> git.saurik.com Git - wxWidgets.git/blame - src/common/gifdecod.cpp
don't crash if conversion of a command line argument to Unicode fails
[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 {
1819a5c1
VZ
470 // Normally, after the alphabet is full and can't grow any
471 // further (ab_free == 4096), encoder should (must?) emit CLEAR
472 // to reset it. This checks whether we really got it, otherwise
473 // the GIF is damaged.
474 if (ab_free > ab_max)
475 {
476 delete[] ab_prefix;
477 delete[] ab_tail;
478 delete[] stack;
479 return wxGIF_INVFORMAT;
480 }
481
482 // This assert seems unnecessary since the condition above
483 // eliminates the only case in which it went false. But I really
484 // don't like being forced to ask "Who in .text could have
485 // written there?!" And I wouldn't have been forced to ask if
486 // this line had already been here.
487 wxASSERT(ab_free < allocSize);
488
b11e8fb6
VZ
489 ab_prefix[ab_free] = lastcode;
490 ab_tail[ab_free] = code;
491 ab_free++;
492
493 if ((ab_free > ab_max) && (ab_bits < 12))
494 {
495 ab_bits++;
496 ab_max = (1 << ab_bits) - 1;
497 }
498 }
499
e34f4f19 500 /* dump stack data to the image buffer */
b11e8fb6
VZ
501 while (pos >= 0)
502 {
e34f4f19
VZ
503 (img->p)[x + (y * (img->w))] = (char) stack[pos];
504 pos--;
b11e8fb6
VZ
505
506 if (++x >= (img->w))
507 {
508 x = 0;
509
510 if (interl)
511 {
512 /* support for interlaced images */
513 switch (pass)
514 {
515 case 1: y += 8; break;
516 case 2: y += 8; break;
517 case 3: y += 4; break;
518 case 4: y += 2; break;
519 }
e34f4f19
VZ
520
521 /* loop until a valid y coordinate has been
522 found, Or if the maximum number of passes has
523 been reached, exit the loop, and stop image
3103e8a9 524 decoding (At this point the image is successfully
e34f4f19
VZ
525 decoded).
526 If we don't loop, but merely set y to some other
527 value, that new value might still be invalid depending
528 on the height of the image. This would cause out of
529 bounds writing.
530 */
531 while (y >= (img->h))
b11e8fb6
VZ
532 {
533 switch (++pass)
534 {
535 case 2: y = 4; break;
536 case 3: y = 2; break;
537 case 4: y = 1; break;
e34f4f19
VZ
538
539 default:
540 /*
541 It's possible we arrive here. For example this
542 happens when the image is interlaced, and the
543 height is 1. Looking at the above cases, the
544 lowest possible y is 1. While the only valid
545 one would be 0 for an image of height 1. So
546 'eventually' the loop will arrive here.
547 This case makes sure this while loop is
548 exited, as well as the 2 other ones.
549 */
550
551 // Set y to a valid coordinate so the local
552 // while loop will be exited. (y = 0 always
553 // is >= img->h since if img->h == 0 the
554 // image is never decoded)
555 y = 0;
556
557 // This will exit the other outer while loop
558 pos = -1;
559
560 // This will halt image decoding.
561 code = ab_fin;
562
563 break;
b11e8fb6
VZ
564 }
565 }
566 }
567 else
568 {
569 /* non-interlaced */
570 y++;
6363699a
VZ
571/*
572Normally image decoding is finished when an End of Information code is
573encountered (code == ab_fin) however some broken encoders write wrong
574"block byte counts" (The first byte value after the "code size" byte),
575being one value too high. It might very well be possible other variants
576of this problem occur as well. The only sensible solution seems to
577be to check for clipping.
578Example of wrong encoding:
579(1 * 1 B/W image, raster data stream follows in hex bytes)
580
58102 << B/W images have a code size of 2
58202 << Block byte count
58344 << LZW packed
58400 << Zero byte count (terminates data stream)
585
586Because the block byte count is 2, the zero byte count is used in the
587decoding process, and decoding is continued after this byte. (While it
588should signal an end of image)
589
590It should be:
59102
59202
59344
59401 << When decoded this correctly includes the End of Information code
59500
596
597Or (Worse solution):
59802
59901
60044
60100
602(The 44 doesn't include an End of Information code, but at least the
603decoder correctly skips to 00 now after decoding, and signals this
604as an End of Information itself)
605*/
606 if (y >= img->h)
607 {
608 code = ab_fin;
609 break;
610 }
b11e8fb6
VZ
611 }
612 }
613 }
614
615 pos = 0;
616 lastcode = readcode;
464122b6
JS
617 }
618 while (code != ab_fin);
619
33ac7e6f
KB
620 delete [] ab_prefix ;
621 delete [] ab_tail ;
622 delete [] stack ;
7679ac63 623
65c36a73 624 return wxGIF_OK;
464122b6
JS
625}
626
627
3c87527e 628// CanRead:
5d3e7b52 629// Returns true if the file looks like a valid GIF, false otherwise.
3c87527e
GRG
630//
631bool wxGIFDecoder::CanRead()
632{
633 unsigned char buf[3];
634
79fa2374 635 if ( !m_f->Read(buf, WXSIZEOF(buf)) )
5d3e7b52 636 return false;
79fa2374 637
30984dea 638 m_f->SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent);
3c87527e 639
79fa2374 640 return memcmp(buf, "GIF", WXSIZEOF(buf)) == 0;
3c87527e
GRG
641}
642
643
464122b6
JS
644// ReadGIF:
645// Reads and decodes one or more GIF images, depending on whether
646// animated GIF support is enabled. Can read GIFs with any bit
647// size (color depth), but the output images are always expanded
648// to 8 bits per pixel. Also, the image palettes always contain
8141573c 649// 256 colors, although some of them may be unused. Returns wxGIF_OK
e4b8154a
GRG
650// (== 0) on success, or an error code if something fails (see
651// header file for details)
464122b6
JS
652//
653int wxGIFDecoder::ReadGIF()
654{
65c36a73
VZ
655 unsigned int ncolors;
656 int bits, interl, transparent, disposal, i;
464122b6
JS
657 long size;
658 long delay;
3ca6a5f0 659 unsigned char type = 0;
464122b6
JS
660 unsigned char pal[768];
661 unsigned char buf[16];
33ac7e6f 662 GIFImage **ppimg;
65c36a73 663 GIFImage *pimg, *pprev;
464122b6 664
3c87527e
GRG
665 /* check GIF signature */
666 if (!CanRead())
b11e8fb6 667 return wxGIF_INVFORMAT;
464122b6 668
8141573c 669 /* check for animated GIF support (ver. >= 89a) */
65c36a73
VZ
670
671 static const size_t headerSize = (3 + 3);
672 m_f->Read(buf, headerSize);
673 if (m_f->LastRead() != headerSize)
674 {
675 return wxGIF_INVFORMAT;
676 }
464122b6 677
464122b6 678 if (memcmp(buf + 3, "89a", 3) < 0)
65c36a73 679 {
5d3e7b52 680 m_anim = false;
65c36a73 681 }
464122b6
JS
682
683 /* read logical screen descriptor block (LSDB) */
65c36a73
VZ
684 static const size_t lsdbSize = (2 + 2 + 1 + 1 + 1);
685 m_f->Read(buf, lsdbSize);
686 if (m_f->LastRead() != lsdbSize)
687 {
688 return wxGIF_INVFORMAT;
689 }
690
464122b6
JS
691 m_screenw = buf[0] + 256 * buf[1];
692 m_screenh = buf[2] + 256 * buf[3];
693
295dec28 694 if ((m_screenw == 0) || (m_screenh == 0))
525b0568
DS
695 {
696 return wxGIF_INVFORMAT;
697 }
698
464122b6
JS
699 /* load global color map if available */
700 if ((buf[4] & 0x80) == 0x80)
701 {
b11e8fb6 702 m_background = buf[5];
464122b6 703
b11e8fb6 704 ncolors = 2 << (buf[4] & 0x07);
65c36a73
VZ
705 size_t numBytes = 3 * ncolors;
706 m_f->Read(pal, numBytes);
707 if (m_f->LastRead() != numBytes)
708 {
709 return wxGIF_INVFORMAT;
710 }
464122b6
JS
711 }
712
713 /* transparent colour, disposal method and delay default to unused */
714 transparent = -1;
715 disposal = -1;
716 delay = -1;
717
718 /* read images */
719 ppimg = &m_pfirst;
720 pprev = NULL;
721 pimg = NULL;
722
5d3e7b52 723 bool done = false;
8141573c 724
525b0568 725 while (!done)
464122b6 726 {
b11e8fb6
VZ
727 type = (unsigned char)m_f->GetC();
728
65c36a73
VZ
729 /*
730 If the end of file has been reached (or an error) and a ";"
731 (0x3B) hasn't been encountered yet, exit the loop. (Without this
732 check the while loop would loop endlessly.) Later on, in the next while
733 loop, the file will be treated as being truncated (But still
734 be decoded as far as possible). returning wxGIF_TRUNCATED is not
735 possible here since some init code is done after this loop.
736 */
737 if (m_f->Eof())// || !m_f->IsOk())
738 {
739 /*
740 type is set to some bogus value, so there's no
741 need to continue evaluating it.
742 */
743 break; // Alternative : "return wxGIF_INVFORMAT;"
744 }
745
b11e8fb6
VZ
746 /* end of data? */
747 if (type == 0x3B)
748 {
5d3e7b52 749 done = true;
b11e8fb6
VZ
750 }
751 else
752 /* extension block? */
753 if (type == 0x21)
754 {
755 if (((unsigned char)m_f->GetC()) == 0xF9)
756 /* graphics control extension, parse it */
757 {
65c36a73
VZ
758 static const size_t gceSize = 6;
759 m_f->Read(buf, gceSize);
760 if (m_f->LastRead() != gceSize)
761 {
762 Destroy();
763 return wxGIF_INVFORMAT;
764 }
b11e8fb6
VZ
765
766 /* read delay and convert from 1/100 of a second to ms */
767 delay = 10 * (buf[2] + 256 * buf[3]);
768
769 /* read transparent colour index, if used */
770 if (buf[1] & 0x01)
771 transparent = buf[4];
772
773 /* read disposal method */
6b5403c8 774 disposal = ((buf[1] & 0x1C) >> 2) - 1;
b11e8fb6
VZ
775 }
776 else
777 /* other extension, skip */
778 {
779 while ((i = (unsigned char)m_f->GetC()) != 0)
780 {
781 m_f->SeekI(i, wxFromCurrent);
65c36a73
VZ
782 if (m_f->Eof())
783 {
5d3e7b52 784 done = true;
65c36a73
VZ
785 break;
786 }
b11e8fb6
VZ
787 }
788 }
789 }
790 else
791 /* image descriptor block? */
792 if (type == 0x2C)
793 {
794 /* allocate memory for IMAGEN struct */
795 pimg = (*ppimg) = new GIFImage();
796
797 if (pimg == NULL)
798 {
799 Destroy();
800 return wxGIF_MEMERR;
801 }
802
803 /* fill in the data */
65c36a73
VZ
804 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
805 m_f->Read(buf, idbSize);
806 if (m_f->LastRead() != idbSize)
807 {
808 Destroy();
809 return wxGIF_INVFORMAT;
810 }
811
b11e8fb6
VZ
812 pimg->left = buf[0] + 256 * buf[1];
813 pimg->top = buf[2] + 256 * buf[3];
bd52bee1 814/*
b11e8fb6
VZ
815 pimg->left = buf[4] + 256 * buf[5];
816 pimg->top = buf[4] + 256 * buf[5];
bd52bee1 817*/
b11e8fb6
VZ
818 pimg->w = buf[4] + 256 * buf[5];
819 pimg->h = buf[6] + 256 * buf[7];
65c36a73 820
295dec28 821 if ((pimg->w == 0) || (pimg->w > m_screenw) || (pimg->h == 0) || (pimg->h > m_screenh))
65c36a73
VZ
822 {
823 Destroy();
824 return wxGIF_INVFORMAT;
825 }
826
b11e8fb6
VZ
827 interl = ((buf[8] & 0x40)? 1 : 0);
828 size = pimg->w * pimg->h;
829
830 pimg->transparent = transparent;
831 pimg->disposal = disposal;
832 pimg->delay = delay;
833 pimg->next = NULL;
834 pimg->prev = pprev;
835 pprev = pimg;
836 ppimg = &pimg->next;
837
838 /* allocate memory for image and palette */
839 pimg->p = (unsigned char *) malloc((size_t)size);
840 pimg->pal = (unsigned char *) malloc(768);
841
842 if ((!pimg->p) || (!pimg->pal))
843 {
844 Destroy();
845 return wxGIF_MEMERR;
846 }
847
848 /* load local color map if available, else use global map */
849 if ((buf[8] & 0x80) == 0x80)
850 {
851 ncolors = 2 << (buf[8] & 0x07);
65c36a73 852 size_t numBytes = 3 * ncolors;
295dec28
DS
853 m_f->Read(pimg->pal, numBytes);
854 if (m_f->LastRead() != numBytes)
65c36a73
VZ
855 {
856 Destroy();
857 return wxGIF_INVFORMAT;
858 }
b11e8fb6
VZ
859 }
860 else
65c36a73 861 {
b11e8fb6 862 memcpy(pimg->pal, pal, 768);
65c36a73 863 }
b11e8fb6
VZ
864
865 /* get initial code size from first byte in raster data */
866 bits = (unsigned char)m_f->GetC();
525b0568
DS
867 if (bits == 0)
868 {
869 Destroy();
870 return wxGIF_INVFORMAT;
871 }
b11e8fb6
VZ
872
873 /* decode image */
65c36a73
VZ
874 int result = dgif(pimg, interl, bits);
875 if (result != wxGIF_OK)
876 {
877 Destroy();
878 return result;
879 }
b11e8fb6
VZ
880 m_nimages++;
881
882 /* if this is not an animated GIF, exit after first image */
883 if (!m_anim)
5d3e7b52 884 done = true;
b11e8fb6 885 }
464122b6
JS
886 }
887
525b0568 888 if (m_nimages <= 0)
464122b6 889 {
65c36a73
VZ
890 Destroy();
891 return wxGIF_INVFORMAT;
464122b6
JS
892 }
893
65c36a73
VZ
894 /* setup image pointers */
895 m_image = 1;
896 m_plast = pimg;
897 m_pimage = m_pfirst;
898
8141573c
GRG
899 /* try to read to the end of the stream */
900 while (type != 0x3B)
901 {
ef3a5e0a
VS
902 if (!m_f->IsOk())
903 return wxGIF_TRUNCATED;
65c36a73 904
b11e8fb6
VZ
905 type = (unsigned char)m_f->GetC();
906
907 if (type == 0x21)
908 {
909 /* extension type */
910 (void) m_f->GetC();
911
912 /* skip all data */
913 while ((i = (unsigned char)m_f->GetC()) != 0)
914 {
915 m_f->SeekI(i, wxFromCurrent);
916 }
917 }
918 else if (type == 0x2C)
919 {
920 /* image descriptor block */
65c36a73
VZ
921 static const size_t idbSize = (2 + 2 + 2 + 2 + 1);
922 m_f->Read(buf, idbSize);
923 if (m_f->LastRead() != idbSize)
924 {
925 Destroy();
926 return wxGIF_INVFORMAT;
927 }
b11e8fb6
VZ
928
929 /* local color map */
930 if ((buf[8] & 0x80) == 0x80)
931 {
932 ncolors = 2 << (buf[8] & 0x07);
7ac31c42
WS
933 wxFileOffset pos = m_f->TellI();
934 wxFileOffset numBytes = 3 * ncolors;
65c36a73
VZ
935 m_f->SeekI(numBytes, wxFromCurrent);
936 if (m_f->TellI() != (pos + numBytes))
937 {
938 Destroy();
939 return wxGIF_INVFORMAT;
940 }
b11e8fb6
VZ
941 }
942
943 /* initial code size */
944 (void) m_f->GetC();
945
946 /* skip all data */
947 while ((i = (unsigned char)m_f->GetC()) != 0)
948 {
949 m_f->SeekI(i, wxFromCurrent);
950 }
951 }
952 else if ((type != 0x3B) && (type != 00)) /* testing */
953 {
954 /* images are OK, but couldn't read to the end of the stream */
955 return wxGIF_TRUNCATED;
956 }
8141573c
GRG
957 }
958
e4b8154a 959 return wxGIF_OK;
464122b6
JS
960}
961
7be110e3 962#endif // wxUSE_STREAMS && wxUSE_GIF