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