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