1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/gifdecod.cpp 
   3 // Purpose:     wxGIFDecoder, GIF reader for wxImage and wxAnimation 
   4 // Author:      Guillermo Rodriguez Garcia <guille@iies.es> 
   7 // Copyright:   (c) Guillermo Rodriguez Garcia 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // For compilers that support precompilation, includes "wx.h". 
  12 #include "wx/wxprec.h" 
  18 #if wxUSE_STREAMS && wxUSE_GIF 
  21     #include "wx/palette.h" 
  26 #include "wx/gifdecod.h" 
  30 //--------------------------------------------------------------------------- 
  32 //--------------------------------------------------------------------------- 
  34 // internal class for storing GIF image data 
  41     unsigned int w
;                 /* width */ 
  42     unsigned int h
;                 /* height */ 
  43     unsigned int left
;              /* x coord (in logical screen) */ 
  44     unsigned int top
;               /* y coord (in logical screen) */ 
  45     int transparent
;                /* transparent color index (-1 = none) */ 
  46     wxAnimationDisposal disposal
;   /* disposal method */ 
  47     long delay
;                     /* delay in ms (-1 = unused) */ 
  48     unsigned char *p
;               /* bitmap */ 
  49     unsigned char *pal
;             /* palette */ 
  50     unsigned int ncolours
;          /* number of colours */ 
  52     DECLARE_NO_COPY_CLASS(GIFImage
) 
  57 //--------------------------------------------------------------------------- 
  58 // GIFImage constructor 
  59 //--------------------------------------------------------------------------- 
  67     disposal 
= wxANIM_DONOTREMOVE
; 
  69     p 
= (unsigned char *) NULL
; 
  70     pal 
= (unsigned char *) NULL
; 
  74 //--------------------------------------------------------------------------- 
  75 // wxGIFDecoder constructor and destructor 
  76 //--------------------------------------------------------------------------- 
  78 wxGIFDecoder::wxGIFDecoder() 
  82 wxGIFDecoder::~wxGIFDecoder() 
  87 void wxGIFDecoder::Destroy() 
  89     wxASSERT(m_nFrames
==m_frames
.GetCount()); 
  90     for (size_t i
=0; i
<m_nFrames
; i
++) 
  92         GIFImage 
*f 
= (GIFImage
*)m_frames
[i
]; 
 103 //--------------------------------------------------------------------------- 
 104 // Convert this image to a wxImage object 
 105 //--------------------------------------------------------------------------- 
 107 // This function was designed by Vaclav Slavik 
 109 bool wxGIFDecoder::ConvertToImage(size_t frame
, wxImage 
*image
) const 
 111     unsigned char *src
, *dst
, *pal
; 
 115     /* just in case... */ 
 118     /* create the image */ 
 119     wxSize sz 
= GetFrameSize(frame
); 
 120     image
->Create(sz
.GetWidth(), sz
.GetHeight()); 
 125     pal 
= GetPalette(frame
); 
 126     src 
= GetData(frame
); 
 127     dst 
= image
->GetData(); 
 128     transparent 
= GetTransparentColourIndex(frame
); 
 130     /* set transparent colour mask */ 
 131     if (transparent 
!= -1) 
 133         for (i 
= 0; i 
< GetNcolours(frame
); i
++) 
 135             if ((pal
[3 * i 
+ 0] == 255) && 
 136                 (pal
[3 * i 
+ 1] == 0) && 
 137                 (pal
[3 * i 
+ 2] == 255)) 
 139                 pal
[3 * i 
+ 2] = 254; 
 143         pal
[3 * transparent 
+ 0] = 255, 
 144         pal
[3 * transparent 
+ 1] = 0, 
 145         pal
[3 * transparent 
+ 2] = 255; 
 147         image
->SetMaskColour(255, 0, 255); 
 150         image
->SetMask(false); 
 153     unsigned char r
[256]; 
 154     unsigned char g
[256]; 
 155     unsigned char b
[256]; 
 157     for (i 
= 0; i 
< 256; i
++) 
 164     image
->SetPalette(wxPalette(GetNcolours(frame
), r
, g
, b
)); 
 165 #endif // wxUSE_PALETTE 
 167     /* copy image data */ 
 168     unsigned long npixel 
= sz
.GetWidth() * sz
.GetHeight(); 
 169     for (i 
= 0; i 
< npixel
; i
++, src
++) 
 171         *(dst
++) = pal
[3 * (*src
) + 0]; 
 172         *(dst
++) = pal
[3 * (*src
) + 1]; 
 173         *(dst
++) = pal
[3 * (*src
) + 2]; 
 180 //--------------------------------------------------------------------------- 
 182 //--------------------------------------------------------------------------- 
 184 #define GetFrame(n)     ((GIFImage*)m_frames[n]) 
 187 // Get data for current frame 
 189 wxSize 
wxGIFDecoder::GetFrameSize(size_t frame
) const  
 191     return wxSize(GetFrame(frame
)->w
, GetFrame(frame
)->h
); 
 194 wxPoint 
wxGIFDecoder::GetFramePosition(size_t frame
) const 
 196     return wxPoint(GetFrame(frame
)->left
, GetFrame(frame
)->top
); 
 199 wxAnimationDisposal 
wxGIFDecoder::GetDisposalMethod(size_t frame
) const 
 201     return GetFrame(frame
)->disposal
; 
 204 long wxGIFDecoder::GetDelay(size_t frame
) const 
 206     return GetFrame(frame
)->delay
; 
 209 wxColour 
wxGIFDecoder::GetTransparentColour(size_t frame
) const 
 211     unsigned char *pal 
= GetFrame(frame
)->pal
; 
 212     int n 
= GetFrame(frame
)->transparent
; 
 216     return wxColour(pal
[n
*3 + 0], 
 221 unsigned char* wxGIFDecoder::GetData(size_t frame
) const    { return (GetFrame(frame
)->p
); } 
 222 unsigned char* wxGIFDecoder::GetPalette(size_t frame
) const { return (GetFrame(frame
)->pal
); } 
 223 unsigned int wxGIFDecoder::GetNcolours(size_t frame
) const  { return (GetFrame(frame
)->ncolours
); } 
 224 int wxGIFDecoder::GetTransparentColourIndex(size_t frame
) const  { return (GetFrame(frame
)->transparent
); } 
 228 //--------------------------------------------------------------------------- 
 229 // GIF reading and decoding 
 230 //--------------------------------------------------------------------------- 
 233 //  Reads the next code from the file stream, with size 'bits' 
 235 int wxGIFDecoder::getcode(wxInputStream
& stream
, int bits
, int ab_fin
) 
 237     unsigned int mask
;          /* bit mask */ 
 238     unsigned int code
;          /* code (result) */ 
 240     /* get remaining bits from last byte read */ 
 241     mask 
= (1 << bits
) - 1; 
 242     code 
= (m_lastbyte 
>> (8 - m_restbits
)) & mask
; 
 244     /* keep reading new bytes while needed */ 
 245     while (bits 
> m_restbits
) 
 247         /* if no bytes left in this block, read the next block */ 
 250             m_restbyte 
= (unsigned char)stream
.GetC(); 
 252             /* Some encoders are a bit broken: instead of issuing 
 253              * an end-of-image symbol (ab_fin) they come up with 
 254              * a zero-length subblock!! We catch this here so 
 255              * that the decoder sees an ab_fin code. 
 264             stream
.Read((void *) m_buffer
, m_restbyte
); 
 265             if (stream
.LastRead() != m_restbyte
) 
 273         /* read next byte and isolate the bits we need */ 
 274         m_lastbyte 
= (unsigned char) (*m_bufp
++); 
 275         mask       
= (1 << (bits 
- m_restbits
)) - 1; 
 276         code       
= code 
+ ((m_lastbyte 
& mask
) << m_restbits
); 
 279         /* adjust total number of bits extracted from the buffer */ 
 280         m_restbits 
= m_restbits 
+ 8; 
 283     /* find number of bits remaining for next code */ 
 284     m_restbits 
= (m_restbits 
- bits
); 
 291 //  GIF decoding function. The initial code size (aka root size) 
 292 //  is 'bits'. Supports interlaced images (interl == 1). 
 293 //  Returns wxGIF_OK (== 0) on success, or an error code if something 
 294 // fails (see header file for details) 
 295 wxGIFErrorCode 
wxGIFDecoder::dgif(wxInputStream
& stream
, GIFImage 
*img
, int interl
, int bits
) 
 297     static const int allocSize 
= 4096 + 1; 
 298     int *ab_prefix 
= new int[allocSize
]; /* alphabet (prefixes) */ 
 299     if (ab_prefix 
== NULL
) 
 304     int *ab_tail 
= new int[allocSize
];   /* alphabet (tails) */ 
 311     int *stack 
= new int[allocSize
];     /* decompression stack */ 
 319     int ab_clr
;                     /* clear code */ 
 320     int ab_fin
;                     /* end of info code */ 
 321     int ab_bits
;                    /* actual symbol width, in bits */ 
 322     int ab_free
;                    /* first free position in alphabet */ 
 323     int ab_max
;                     /* last possible character in alphabet */ 
 324     int pass
;                       /* pass number in interlaced images */ 
 325     int pos
;                        /* index into decompresion stack */ 
 326     unsigned int x
, y
;              /* position in image buffer */ 
 328     int code
, readcode
, lastcode
, abcabca
; 
 330     /* these won't change */ 
 331     ab_clr 
= (1 << bits
); 
 332     ab_fin 
= (1 << bits
) + 1; 
 334     /* these will change through the decompression proccess */ 
 336     ab_free  
= (1 << bits
) + 2; 
 337     ab_max   
= (1 << ab_bits
) - 1; 
 343     /* reset decoder vars */ 
 351         readcode 
= code 
= getcode(stream
, ab_bits
, ab_fin
); 
 354         if (code 
== ab_fin
) break; 
 356         /* reset alphabet? */ 
 359             /* reset main variables */ 
 361             ab_free  
= (1 << bits
) + 2; 
 362             ab_max   
= (1 << ab_bits
) - 1; 
 366             /* skip to next code */ 
 370         /* unknown code: special case (like in ABCABCA) */ 
 373             code 
= lastcode
;            /* take last string */ 
 374             stack
[pos
++] = abcabca
;     /* add first character */ 
 377         /* build the string for this code in the stack */ 
 378         while (code 
> ab_clr
) 
 380             stack
[pos
++] = ab_tail
[code
]; 
 381             code         
= ab_prefix
[code
]; 
 383             // Don't overflow. This shouldn't happen with normal 
 384             // GIF files, the allocSize of 4096+1 is enough. This 
 385             // will only happen with badly formed GIFs. 
 386             if (pos 
>= allocSize
) 
 391                 return wxGIF_INVFORMAT
; 
 395         if (pos 
>= allocSize
) 
 400             return wxGIF_INVFORMAT
; 
 403         stack
[pos
] = code
;              /* push last code into the stack */ 
 404         abcabca    
= code
;              /* save for special case */ 
 406         /* make new entry in alphabet (only if NOT just cleared) */ 
 409             // Normally, after the alphabet is full and can't grow any 
 410             // further (ab_free == 4096), encoder should (must?) emit CLEAR 
 411             // to reset it. This checks whether we really got it, otherwise 
 412             // the GIF is damaged. 
 413             if (ab_free 
> ab_max
) 
 418                 return wxGIF_INVFORMAT
; 
 421             // This assert seems unnecessary since the condition above 
 422             // eliminates the only case in which it went false. But I really 
 423             // don't like being forced to ask "Who in .text could have 
 424             // written there?!" And I wouldn't have been forced to ask if 
 425             // this line had already been here. 
 426             wxASSERT(ab_free 
< allocSize
); 
 428             ab_prefix
[ab_free
] = lastcode
; 
 429             ab_tail
[ab_free
]   = code
; 
 432             if ((ab_free 
> ab_max
) && (ab_bits 
< 12)) 
 435                 ab_max 
= (1 << ab_bits
) - 1; 
 439         /* dump stack data to the image buffer */ 
 442             (img
->p
)[x 
+ (y 
* (img
->w
))] = (char) stack
[pos
]; 
 451                     /* support for interlaced images */ 
 454                         case 1: y 
+= 8; break; 
 455                         case 2: y 
+= 8; break; 
 456                         case 3: y 
+= 4; break; 
 457                         case 4: y 
+= 2; break; 
 460                     /* loop until a valid y coordinate has been 
 461                     found, Or if the maximum number of passes has 
 462                     been reached, exit the loop, and stop image 
 463                     decoding (At this point the image is successfully 
 465                     If we don't loop, but merely set y to some other 
 466                     value, that new value might still be invalid depending 
 467                     on the height of the image. This would cause out of 
 470                     while (y 
>= (img
->h
)) 
 474                             case 2: y 
= 4; break; 
 475                             case 3: y 
= 2; break; 
 476                             case 4: y 
= 1; break; 
 480                                 It's possible we arrive here. For example this 
 481                                 happens when the image is interlaced, and the 
 482                                 height is 1. Looking at the above cases, the 
 483                                 lowest possible y is 1. While the only valid 
 484                                 one would be 0 for an image of height 1. So 
 485                                 'eventually' the loop will arrive here. 
 486                                 This case makes sure this while loop is 
 487                                 exited, as well as the 2 other ones. 
 490                                 // Set y to a valid coordinate so the local 
 491                                 // while loop will be exited. (y = 0 always 
 492                                 // is >= img->h since if img->h == 0 the 
 493                                 // image is never decoded) 
 496                                 // This will exit the other outer while loop 
 499                                 // This will halt image decoding. 
 511 Normally image decoding is finished when an End of Information code is 
 512 encountered (code == ab_fin) however some broken encoders write wrong 
 513 "block byte counts" (The first byte value after the "code size" byte), 
 514 being one value too high. It might very well be possible other variants 
 515 of this problem occur as well. The only sensible solution seems to 
 516 be to check for clipping. 
 517 Example of wrong encoding: 
 518 (1 * 1 B/W image, raster data stream follows in hex bytes) 
 520 02  << B/W images have a code size of 2 
 521 02  << Block byte count 
 523 00  << Zero byte count (terminates data stream) 
 525 Because the block byte count is 2, the zero byte count is used in the 
 526 decoding process, and decoding is continued after this byte. (While it 
 527 should signal an end of image) 
 533 01  << When decoded this correctly includes the End of Information code 
 541 (The 44 doesn't include an End of Information code, but at least the 
 542 decoder correctly skips to 00 now after decoding, and signals this 
 543 as an End of Information itself) 
 557     while (code 
!= ab_fin
); 
 559     delete [] ab_prefix 
; 
 568 //  Returns true if the file looks like a valid GIF, false otherwise. 
 570 bool wxGIFDecoder::CanRead(wxInputStream 
&stream
) const 
 572     unsigned char buf
[3]; 
 574     if ( !stream
.Read(buf
, WXSIZEOF(buf
)) ) 
 577     stream
.SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
); 
 579     return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0; 
 584 //  Reads and decodes one or more GIF images, depending on whether 
 585 //  animated GIF support is enabled. Can read GIFs with any bit 
 586 //  size (color depth), but the output images are always expanded 
 587 //  to 8 bits per pixel. Also, the image palettes always contain 
 588 //  256 colors, although some of them may be unused. Returns wxGIF_OK 
 589 //  (== 0) on success, or an error code if something fails (see 
 590 //  header file for details) 
 592 wxGIFErrorCode 
wxGIFDecoder::LoadGIF(wxInputStream
& stream
) 
 594     unsigned int  global_ncolors 
= 0; 
 595     int           bits
, interl
, transparent
, i
; 
 596     wxAnimationDisposal disposal
; 
 599     unsigned char type 
= 0; 
 600     unsigned char pal
[768]; 
 601     unsigned char buf
[16]; 
 604     /* check GIF signature */ 
 605     if (!CanRead(stream
)) 
 606         return wxGIF_INVFORMAT
; 
 608     /* check for animated GIF support (ver. >= 89a) */ 
 610     static const size_t headerSize 
= (3 + 3); 
 611     stream
.Read(buf
, headerSize
); 
 612     if (stream
.LastRead() != headerSize
) 
 614         return wxGIF_INVFORMAT
; 
 617     if (memcmp(buf 
+ 3, "89a", 3) < 0) 
 622     /* read logical screen descriptor block (LSDB) */ 
 623     static const size_t lsdbSize 
= (2 + 2 + 1 + 1 + 1); 
 624     stream
.Read(buf
, lsdbSize
); 
 625     if (stream
.LastRead() != lsdbSize
) 
 627         return wxGIF_INVFORMAT
; 
 630     m_szAnimation
.SetWidth( buf
[0] + 256 * buf
[1] ); 
 631     m_szAnimation
.SetHeight( buf
[2] + 256 * buf
[3] ); 
 633     if ((m_szAnimation
.GetWidth() == 0) || (m_szAnimation
.GetHeight() == 0)) 
 635         return wxGIF_INVFORMAT
; 
 638     /* load global color map if available */ 
 639     if ((buf
[4] & 0x80) == 0x80) 
 641         int backgroundColIndex 
= buf
[5]; 
 643         global_ncolors 
= 2 << (buf
[4] & 0x07); 
 644         size_t numBytes 
= 3 * global_ncolors
; 
 645         stream
.Read(pal
, numBytes
); 
 646         if (stream
.LastRead() != numBytes
) 
 648             return wxGIF_INVFORMAT
; 
 651         m_background
.Set(pal
[backgroundColIndex
*3 + 0], 
 652                          pal
[backgroundColIndex
*3 + 1], 
 653                          pal
[backgroundColIndex
*3 + 2]); 
 656     /* transparent colour, disposal method and delay default to unused */ 
 658     disposal 
= wxANIM_UNSPECIFIED
; 
 664         type 
= (unsigned char)stream
.GetC(); 
 667         If the end of file has been reached (or an error) and a ";" 
 668         (0x3B) hasn't been encountered yet, exit the loop. (Without this 
 669         check the while loop would loop endlessly.) Later on, in the next while 
 670         loop, the file will be treated as being truncated (But still 
 671         be decoded as far as possible). returning wxGIF_TRUNCATED is not 
 672         possible here since some init code is done after this loop. 
 674         if (stream
.Eof())// || !stream.IsOk()) 
 677             type is set to some bogus value, so there's no 
 678             need to continue evaluating it. 
 680             break; // Alternative : "return wxGIF_INVFORMAT;" 
 689         /* extension block? */ 
 692             if (((unsigned char)stream
.GetC()) == 0xF9) 
 693             /* graphics control extension, parse it */ 
 695                 static const size_t gceSize 
= 6; 
 696                 stream
.Read(buf
, gceSize
); 
 697                 if (stream
.LastRead() != gceSize
) 
 700                     return wxGIF_INVFORMAT
; 
 703                 /* read delay and convert from 1/100 of a second to ms */ 
 704                 delay 
= 10 * (buf
[2] + 256 * buf
[3]); 
 706                 /* read transparent colour index, if used */ 
 708                     transparent 
= buf
[4]; 
 710                 /* read disposal method */ 
 711                 disposal 
= (wxAnimationDisposal
)(((buf
[1] & 0x1C) >> 2) - 1); 
 714             /* other extension, skip */ 
 716                 while ((i 
= (unsigned char)stream
.GetC()) != 0) 
 718                     stream
.SeekI(i
, wxFromCurrent
); 
 728         /* image descriptor block? */ 
 731             /* allocate memory for IMAGEN struct */ 
 732             GIFImage 
*pimg 
= new GIFImage(); 
 740             /* fill in the data */ 
 741             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 742             stream
.Read(buf
, idbSize
); 
 743             if (stream
.LastRead() != idbSize
) 
 746                 return wxGIF_INVFORMAT
; 
 749             pimg
->left 
= buf
[0] + 256 * buf
[1]; 
 750             pimg
->top 
= buf
[2] + 256 * buf
[3]; 
 752             pimg->left = buf[4] + 256 * buf[5]; 
 753             pimg->top = buf[4] + 256 * buf[5]; 
 755             pimg
->w 
= buf
[4] + 256 * buf
[5]; 
 756             pimg
->h 
= buf
[6] + 256 * buf
[7]; 
 758             if ((pimg
->w 
== 0) || (pimg
->w 
> (unsigned int)m_szAnimation
.GetWidth()) ||  
 759                 (pimg
->h 
== 0) || (pimg
->h 
> (unsigned int)m_szAnimation
.GetHeight())) 
 762                 return wxGIF_INVFORMAT
; 
 765             interl 
= ((buf
[8] & 0x40)? 1 : 0); 
 766             size 
= pimg
->w 
* pimg
->h
; 
 768             pimg
->transparent 
= transparent
; 
 769             pimg
->disposal 
= disposal
; 
 772             /* allocate memory for image and palette */ 
 773             pimg
->p   
= (unsigned char *) malloc((size_t)size
); 
 774             pimg
->pal 
= (unsigned char *) malloc(768); 
 776             if ((!pimg
->p
) || (!pimg
->pal
)) 
 782             /* load local color map if available, else use global map */ 
 783             if ((buf
[8] & 0x80) == 0x80) 
 785                 unsigned int local_ncolors 
= 2 << (buf
[8] & 0x07); 
 786                 size_t numBytes 
= 3 * local_ncolors
; 
 787                 stream
.Read(pimg
->pal
, numBytes
); 
 788                 pimg
->ncolours 
= local_ncolors
; 
 789                 if (stream
.LastRead() != numBytes
) 
 792                     return wxGIF_INVFORMAT
; 
 797                 memcpy(pimg
->pal
, pal
, 768); 
 798                 pimg
->ncolours 
= global_ncolors
; 
 801             /* get initial code size from first byte in raster data */ 
 802             bits 
= (unsigned char)stream
.GetC(); 
 806                 return wxGIF_INVFORMAT
; 
 810             wxGIFErrorCode result 
= dgif(stream
, pimg
, interl
, bits
); 
 811             if (result 
!= wxGIF_OK
) 
 817             /* add the image to our frame array */ 
 818             m_frames
.Add((void*)pimg
); 
 821             /* if this is not an animated GIF, exit after first image */ 
 830         return wxGIF_INVFORMAT
; 
 833     /* try to read to the end of the stream */ 
 837             return wxGIF_TRUNCATED
; 
 839         type 
= (unsigned char)stream
.GetC(); 
 844             (void) stream
.GetC(); 
 847             while ((i 
= (unsigned char)stream
.GetC()) != 0) 
 849                 stream
.SeekI(i
, wxFromCurrent
); 
 852         else if (type 
== 0x2C) 
 854             /* image descriptor block */ 
 855             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 856             stream
.Read(buf
, idbSize
); 
 857             if (stream
.LastRead() != idbSize
) 
 860                 return wxGIF_INVFORMAT
; 
 863             /* local color map */ 
 864             if ((buf
[8] & 0x80) == 0x80) 
 866                 unsigned int local_ncolors 
= 2 << (buf
[8] & 0x07); 
 867                 wxFileOffset pos 
= stream
.TellI(); 
 868                 wxFileOffset numBytes 
= 3 * local_ncolors
; 
 869                 stream
.SeekI(numBytes
, wxFromCurrent
); 
 870                 if (stream
.TellI() != (pos 
+ numBytes
)) 
 873                     return wxGIF_INVFORMAT
; 
 877             /* initial code size */ 
 878             (void) stream
.GetC(); 
 881             while ((i 
= (unsigned char)stream
.GetC()) != 0) 
 883                 stream
.SeekI(i
, wxFromCurrent
); 
 886         else if ((type 
!= 0x3B) && (type 
!= 00)) /* testing */ 
 888             /* images are OK, but couldn't read to the end of the stream */ 
 889             return wxGIF_TRUNCATED
; 
 896 #endif // wxUSE_STREAMS && wxUSE_GIF