]> git.saurik.com Git - wxWidgets.git/blob - src/common/gifdecod.cpp
OS/2 NativeFontInfo support
[wxWidgets.git] / src / common / gifdecod.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gifdecod.cpp
3 // Purpose: wxGIFDecoder, GIF reader for wxImage and wxAnimation
4 // Author: Guillermo Rodriguez Garcia <guille@iies.es>
5 // Version: 3.04
6 // RCS-ID: $Id$
7 // Copyright: (c) Guillermo Rodriguez Garcia
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
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
23 # include "wx/defs.h"
24 #endif
25
26 #if wxUSE_STREAMS && wxUSE_GIF
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include "wx/gifdecod.h"
31
32
33 //---------------------------------------------------------------------------
34 // wxGIFDecoder constructor and destructor
35 //---------------------------------------------------------------------------
36
37 wxGIFDecoder::wxGIFDecoder(wxInputStream *s, bool anim)
38 {
39 m_f = s;
40 m_anim = anim;
41
42 m_background = -1;
43 m_screenw = 0;
44 m_screenh = 0;
45
46 m_pimage = NULL;
47 m_pfirst = NULL;
48 m_plast = NULL;
49 m_image = 0;
50 m_nimages = 0;
51 }
52
53 wxGIFDecoder::~wxGIFDecoder()
54 {
55 Destroy();
56 }
57
58 void wxGIFDecoder::Destroy()
59 {
60 GIFImage *pimg, *paux;
61
62 pimg = m_pfirst;
63
64 while (pimg != NULL)
65 {
66 paux = pimg->next;
67 free(pimg->p);
68 free(pimg->pal);
69 delete pimg;
70 pimg = paux;
71 }
72
73 m_pimage = NULL;
74 m_pfirst = NULL;
75 m_plast = NULL;
76 m_image = 0;
77 m_nimages = 0;
78 }
79
80
81 //---------------------------------------------------------------------------
82 // Convert this image to a wxImage object
83 //---------------------------------------------------------------------------
84
85 // This function was designed by Vaclav Slavik
86
87 bool wxGIFDecoder::ConvertToImage(wxImage *image) const
88 {
89 unsigned char *src, *dst, *pal;
90 unsigned long i;
91 int transparent;
92
93 /* just in case... */
94 image->Destroy();
95
96 /* create the image */
97 image->Create(GetWidth(), GetHeight());
98
99 if (!image->Ok())
100 return FALSE;
101
102 pal = GetPalette();
103 src = GetData();
104 dst = image->GetData();
105 transparent = GetTransparentColour();
106
107 /* set transparent colour mask */
108 if (transparent != -1)
109 {
110 for (i = 0; i < 256; i++)
111 {
112 if ((pal[3 * i + 0] == 255) &&
113 (pal[3 * i + 1] == 0) &&
114 (pal[3 * i + 2] == 255))
115 {
116 pal[3 * i + 2] = 254;
117 }
118 }
119
120 pal[3 * transparent + 0] = 255,
121 pal[3 * transparent + 1] = 0,
122 pal[3 * transparent + 2] = 255;
123
124 image->SetMaskColour(255, 0, 255);
125 }
126 else
127 image->SetMask(FALSE);
128
129 #if wxUSE_PALETTE
130 if (pal)
131 {
132 unsigned char r[256];
133 unsigned char g[256];
134 unsigned char b[256];
135
136 for (i = 0; i < 256; i++)
137 {
138 r[i] = pal[3*i + 0];
139 g[i] = pal[3*i + 1];
140 b[i] = pal[3*i + 2];
141 }
142
143 image->SetPalette(wxPalette(256, r, g, b));
144 }
145 #endif // wxUSE_PALETTE
146
147 /* copy image data */
148 for (i = 0; i < (GetWidth() * GetHeight()); i++, src++)
149 {
150 *(dst++) = pal[3 * (*src) + 0];
151 *(dst++) = pal[3 * (*src) + 1];
152 *(dst++) = pal[3 * (*src) + 2];
153 }
154
155 return TRUE;
156 }
157
158
159 //---------------------------------------------------------------------------
160 // Data accessors
161 //---------------------------------------------------------------------------
162
163 // Get data for current frame
164
165 int wxGIFDecoder::GetFrameIndex() const { return m_image; }
166 unsigned char* wxGIFDecoder::GetData() const { return (m_pimage->p); }
167 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage->pal); }
168 unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage->w); }
169 unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage->h); }
170 unsigned int wxGIFDecoder::GetTop() const { return (m_pimage->top); }
171 unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage->left); }
172 int wxGIFDecoder::GetTransparentColour() const { return (m_pimage->transparent); }
173 int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage->disposal); }
174 long wxGIFDecoder::GetDelay() const { return (m_pimage->delay); }
175
176 // Get global data
177
178 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw; }
179 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh; }
180 int wxGIFDecoder::GetBackgroundColour() const { return m_background; }
181 int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages; }
182 bool wxGIFDecoder::IsAnimation() const { return (m_nimages > 1); }
183
184
185 //---------------------------------------------------------------------------
186 // Functions to move through the animation
187 //---------------------------------------------------------------------------
188
189 bool wxGIFDecoder::GoFirstFrame()
190 {
191 if (!IsAnimation())
192 return FALSE;
193
194 m_image = 1;
195 m_pimage = m_pfirst;
196 return TRUE;
197 }
198
199 bool wxGIFDecoder::GoLastFrame()
200 {
201 if (!IsAnimation())
202 return FALSE;
203
204 m_image = m_nimages;
205 m_pimage = m_plast;
206 return TRUE;
207 }
208
209 bool wxGIFDecoder::GoNextFrame(bool cyclic)
210 {
211 if (!IsAnimation())
212 return FALSE;
213
214 if ((m_image < m_nimages) || (cyclic))
215 {
216 m_pimage = m_pimage->next;
217 m_image++;
218
219 if (!m_pimage)
220 {
221 m_image = 1;
222 m_pimage = m_pfirst;
223 }
224
225 return TRUE;
226 }
227 else
228 return FALSE;
229 }
230
231 bool wxGIFDecoder::GoPrevFrame(bool cyclic)
232 {
233 if (!IsAnimation())
234 return FALSE;
235
236 if ((m_image > 1) || (cyclic))
237 {
238 m_pimage = m_pimage->prev;
239 m_image--;
240
241 if (!m_pimage)
242 {
243 m_image = m_nimages;
244 m_pimage = m_plast;
245 }
246
247 return TRUE;
248 }
249 else
250 return FALSE;
251 }
252
253 bool wxGIFDecoder::GoFrame(int which)
254 {
255 int i;
256
257 if (!IsAnimation())
258 return FALSE;
259
260 if ((which >= 1) && (which <= m_nimages))
261 {
262 m_pimage = m_pfirst;
263
264 for (i = 1; i < which; i++)
265 m_pimage = m_pimage->next;
266
267 return TRUE;
268 }
269 else
270 return FALSE;
271 }
272
273
274 //---------------------------------------------------------------------------
275 // GIF reading and decoding
276 //---------------------------------------------------------------------------
277
278 // getcode:
279 // Reads the next code from the file stream, with size 'bits'
280 //
281 int wxGIFDecoder::getcode(int bits, int ab_fin)
282 {
283 unsigned int mask; /* bit mask */
284 unsigned int code; /* code (result) */
285
286
287 /* get remaining bits from last byte read */
288 mask = (1 << bits) - 1;
289 code = (m_lastbyte >> (8 - m_restbits)) & mask;
290
291 /* keep reading new bytes while needed */
292 while (bits > m_restbits)
293 {
294 /* if no bytes left in this block, read the next block */
295 if (m_restbyte == 0)
296 {
297 m_restbyte = (unsigned char)m_f->GetC();
298
299 /* Some encoders are a bit broken: instead of issuing
300 * an end-of-image symbol (ab_fin) they come up with
301 * a zero-length subblock!! We catch this here so
302 * that the decoder sees an ab_fin code.
303 */
304 if (m_restbyte == 0)
305 {
306 code = ab_fin;
307 break;
308 }
309
310 /* prefetch data */
311 m_f->Read((void *) m_buffer, m_restbyte);
312 m_bufp = m_buffer;
313 }
314
315 /* read next byte and isolate the bits we need */
316 m_lastbyte = (unsigned char) (*m_bufp++);
317 mask = (1 << (bits - m_restbits)) - 1;
318 code = code + ((m_lastbyte & mask) << m_restbits);
319 m_restbyte--;
320
321 /* adjust total number of bits extracted from the buffer */
322 m_restbits = m_restbits + 8;
323 }
324
325 /* find number of bits remaining for next code */
326 m_restbits = (m_restbits - bits);
327
328 return code;
329 }
330
331
332 // dgif:
333 // GIF decoding function. The initial code size (aka root size)
334 // is 'bits'. Supports interlaced images (interl == 1).
335 //
336 int wxGIFDecoder::dgif(GIFImage *img, int interl, int bits)
337 {
338 int *ab_prefix = new int[4096]; /* alphabet (prefixes) */
339 int *ab_tail = new int[4096]; /* alphabet (tails) */
340 int *stack = new int[4096]; /* decompression stack */
341 int ab_clr; /* clear code */
342 int ab_fin; /* end of info code */
343 int ab_bits; /* actual symbol width, in bits */
344 int ab_free; /* first free position in alphabet */
345 int ab_max; /* last possible character in alphabet */
346 int pass; /* pass number in interlaced images */
347 int pos; /* index into decompresion stack */
348 unsigned int x, y; /* position in image buffer */
349
350 int code, readcode, lastcode, abcabca;
351
352 /* these won't change */
353 ab_clr = (1 << bits);
354 ab_fin = (1 << bits) + 1;
355
356 /* these will change through the decompression proccess */
357 ab_bits = bits + 1;
358 ab_free = (1 << bits) + 2;
359 ab_max = (1 << ab_bits) - 1;
360 lastcode = -1;
361 abcabca = -1;
362 pass = 1;
363 pos = x = y = 0;
364
365 /* reset decoder vars */
366 m_restbits = 0;
367 m_restbyte = 0;
368 m_lastbyte = 0;
369
370 do
371 {
372 /* get next code */
373 readcode = code = getcode(ab_bits, ab_fin);
374
375 /* end of image? */
376 if (code == ab_fin) break;
377
378 /* reset alphabet? */
379 if (code == ab_clr)
380 {
381 /* reset main variables */
382 ab_bits = bits + 1;
383 ab_free = (1 << bits) + 2;
384 ab_max = (1 << ab_bits) - 1;
385 lastcode = -1;
386 abcabca = -1;
387
388 /* skip to next code */
389 continue;
390 }
391
392 /* unknown code: special case (like in ABCABCA) */
393 if (code >= ab_free)
394 {
395 code = lastcode; /* take last string */
396 stack[pos++] = abcabca; /* add first character */
397 }
398
399 /* build the string for this code in the stack */
400 while (code > ab_clr)
401 {
402 stack[pos++] = ab_tail[code];
403 code = ab_prefix[code];
404 }
405 stack[pos] = code; /* push last code into the stack */
406 abcabca = code; /* save for special case */
407
408 /* make new entry in alphabet (only if NOT just cleared) */
409 if (lastcode != -1)
410 {
411 ab_prefix[ab_free] = lastcode;
412 ab_tail[ab_free] = code;
413 ab_free++;
414
415 if ((ab_free > ab_max) && (ab_bits < 12))
416 {
417 ab_bits++;
418 ab_max = (1 << ab_bits) - 1;
419 }
420 }
421
422 /* dump stack data to the buffer */
423 while (pos >= 0)
424 {
425 (img->p)[x + (y * (img->w))] = (char)stack[pos--];
426
427 if (++x >= (img->w))
428 {
429 x = 0;
430
431 if (interl)
432 {
433 /* support for interlaced images */
434 switch (pass)
435 {
436 case 1: y += 8; break;
437 case 2: y += 8; break;
438 case 3: y += 4; break;
439 case 4: y += 2; break;
440 }
441 if (y >= (img->h))
442 {
443 switch (++pass)
444 {
445 case 2: y = 4; break;
446 case 3: y = 2; break;
447 case 4: y = 1; break;
448 }
449 }
450 }
451 else
452 {
453 /* non-interlaced */
454 y++;
455 /*
456 Normally image decoding is finished when an End of Information code is
457 encountered (code == ab_fin) however some broken encoders write wrong
458 "block byte counts" (The first byte value after the "code size" byte),
459 being one value too high. It might very well be possible other variants
460 of this problem occur as well. The only sensible solution seems to
461 be to check for clipping.
462 Example of wrong encoding:
463 (1 * 1 B/W image, raster data stream follows in hex bytes)
464
465 02 << B/W images have a code size of 2
466 02 << Block byte count
467 44 << LZW packed
468 00 << Zero byte count (terminates data stream)
469
470 Because the block byte count is 2, the zero byte count is used in the
471 decoding process, and decoding is continued after this byte. (While it
472 should signal an end of image)
473
474 It should be:
475 02
476 02
477 44
478 01 << When decoded this correctly includes the End of Information code
479 00
480
481 Or (Worse solution):
482 02
483 01
484 44
485 00
486 (The 44 doesn't include an End of Information code, but at least the
487 decoder correctly skips to 00 now after decoding, and signals this
488 as an End of Information itself)
489 */
490 if (y >= img->h)
491 {
492 code = ab_fin;
493 break;
494 }
495 }
496 }
497 }
498
499 pos = 0;
500 lastcode = readcode;
501 }
502 while (code != ab_fin);
503
504 delete [] ab_prefix ;
505 delete [] ab_tail ;
506 delete [] stack ;
507
508 return 0;
509 }
510
511
512 // CanRead:
513 // Returns TRUE if the file looks like a valid GIF, FALSE otherwise.
514 //
515 bool wxGIFDecoder::CanRead()
516 {
517 unsigned char buf[3];
518
519 m_f->Read(buf, 3);
520 m_f->SeekI(-3, wxFromCurrent);
521
522 return (memcmp(buf, "GIF", 3) == 0);
523 }
524
525
526 // ReadGIF:
527 // Reads and decodes one or more GIF images, depending on whether
528 // animated GIF support is enabled. Can read GIFs with any bit
529 // size (color depth), but the output images are always expanded
530 // to 8 bits per pixel. Also, the image palettes always contain
531 // 256 colors, although some of them may be unused. Returns wxGIF_OK
532 // (== 0) on success, or an error code if something fails (see
533 // header file for details)
534 //
535 int wxGIFDecoder::ReadGIF()
536 {
537 int ncolors, bits, interl, transparent, disposal, i;
538 long size;
539 long delay;
540 unsigned char type = 0;
541 unsigned char pal[768];
542 unsigned char buf[16];
543 GIFImage **ppimg;
544 GIFImage *pimg, *pprev;
545
546 /* check GIF signature */
547 if (!CanRead())
548 return wxGIF_INVFORMAT;
549
550 /* check for animated GIF support (ver. >= 89a) */
551 m_f->Read(buf, 6);
552
553 if (memcmp(buf + 3, "89a", 3) < 0)
554 m_anim = FALSE;
555
556 /* read logical screen descriptor block (LSDB) */
557 m_f->Read(buf, 7);
558 m_screenw = buf[0] + 256 * buf[1];
559 m_screenh = buf[2] + 256 * buf[3];
560
561 /* load global color map if available */
562 if ((buf[4] & 0x80) == 0x80)
563 {
564 m_background = buf[5];
565
566 ncolors = 2 << (buf[4] & 0x07);
567 m_f->Read(pal, 3 * ncolors);
568 }
569
570 /* transparent colour, disposal method and delay default to unused */
571 transparent = -1;
572 disposal = -1;
573 delay = -1;
574
575 /* read images */
576 ppimg = &m_pfirst;
577 pprev = NULL;
578 pimg = NULL;
579
580 bool done = FALSE;
581
582 while(!done)
583 {
584 type = (unsigned char)m_f->GetC();
585
586 /* end of data? */
587 if (type == 0x3B)
588 {
589 done = TRUE;
590 }
591 else
592 /* extension block? */
593 if (type == 0x21)
594 {
595 if (((unsigned char)m_f->GetC()) == 0xF9)
596 /* graphics control extension, parse it */
597 {
598 m_f->Read(buf, 6);
599
600 /* read delay and convert from 1/100 of a second to ms */
601 delay = 10 * (buf[2] + 256 * buf[3]);
602
603 /* read transparent colour index, if used */
604 if (buf[1] & 0x01)
605 transparent = buf[4];
606
607 /* read disposal method */
608 disposal = (buf[1] & 0x1C) - 1;
609 }
610 else
611 /* other extension, skip */
612 {
613 while ((i = (unsigned char)m_f->GetC()) != 0)
614 {
615 m_f->SeekI(i, wxFromCurrent);
616 }
617 }
618 }
619 else
620 /* image descriptor block? */
621 if (type == 0x2C)
622 {
623 /* allocate memory for IMAGEN struct */
624 pimg = (*ppimg) = new GIFImage();
625
626 if (pimg == NULL)
627 {
628 Destroy();
629 return wxGIF_MEMERR;
630 }
631
632 /* fill in the data */
633 m_f->Read(buf, 9);
634 pimg->left = buf[0] + 256 * buf[1];
635 pimg->top = buf[2] + 256 * buf[3];
636 /*
637 pimg->left = buf[4] + 256 * buf[5];
638 pimg->top = buf[4] + 256 * buf[5];
639 */
640 pimg->w = buf[4] + 256 * buf[5];
641 pimg->h = buf[6] + 256 * buf[7];
642 interl = ((buf[8] & 0x40)? 1 : 0);
643 size = pimg->w * pimg->h;
644
645 pimg->transparent = transparent;
646 pimg->disposal = disposal;
647 pimg->delay = delay;
648 pimg->next = NULL;
649 pimg->prev = pprev;
650 pprev = pimg;
651 ppimg = &pimg->next;
652
653 /* allocate memory for image and palette */
654 pimg->p = (unsigned char *) malloc((size_t)size);
655 pimg->pal = (unsigned char *) malloc(768);
656
657 if ((!pimg->p) || (!pimg->pal))
658 {
659 Destroy();
660 return wxGIF_MEMERR;
661 }
662
663 /* load local color map if available, else use global map */
664 if ((buf[8] & 0x80) == 0x80)
665 {
666 ncolors = 2 << (buf[8] & 0x07);
667 m_f->Read(pimg->pal, 3 * ncolors);
668 }
669 else
670 memcpy(pimg->pal, pal, 768);
671
672 /* get initial code size from first byte in raster data */
673 bits = (unsigned char)m_f->GetC();
674
675 /* decode image */
676 dgif(pimg, interl, bits);
677 m_nimages++;
678
679 /* if this is not an animated GIF, exit after first image */
680 if (!m_anim)
681 done = TRUE;
682 }
683 }
684
685 /* setup image pointers */
686 if (m_nimages != 0)
687 {
688 m_image = 1;
689 m_plast = pimg;
690 m_pimage = m_pfirst;
691 }
692
693 /* try to read to the end of the stream */
694 while (type != 0x3B)
695 {
696 if (!m_f->IsOk())
697 return wxGIF_TRUNCATED;
698
699 type = (unsigned char)m_f->GetC();
700
701 if (type == 0x21)
702 {
703 /* extension type */
704 (void) m_f->GetC();
705
706 /* skip all data */
707 while ((i = (unsigned char)m_f->GetC()) != 0)
708 {
709 m_f->SeekI(i, wxFromCurrent);
710 }
711 }
712 else if (type == 0x2C)
713 {
714 /* image descriptor block */
715 m_f->Read(buf, 9);
716
717 /* local color map */
718 if ((buf[8] & 0x80) == 0x80)
719 {
720 ncolors = 2 << (buf[8] & 0x07);
721 m_f->SeekI(3 * ncolors, wxFromCurrent);
722 }
723
724 /* initial code size */
725 (void) m_f->GetC();
726
727 /* skip all data */
728 while ((i = (unsigned char)m_f->GetC()) != 0)
729 {
730 m_f->SeekI(i, wxFromCurrent);
731 }
732 }
733 else if ((type != 0x3B) && (type != 00)) /* testing */
734 {
735 /* images are OK, but couldn't read to the end of the stream */
736 return wxGIF_TRUNCATED;
737 }
738 }
739
740 return wxGIF_OK;
741 }
742
743 #endif // wxUSE_STREAMS && wxUSE_GIF