]>
git.saurik.com Git - wxWidgets.git/blob - src/common/gifdecod.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   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" 
  20 #  include "wx/palette.h" 
  23 #if wxUSE_STREAMS && wxUSE_GIF 
  27 #include "wx/gifdecod.h" 
  30 //--------------------------------------------------------------------------- 
  31 // GIFImage constructor 
  32 //--------------------------------------------------------------------------- 
  42     p 
= (unsigned char *) NULL
; 
  43     pal 
= (unsigned char *) NULL
; 
  44     next 
= (GIFImage 
*) NULL
; 
  45     prev 
= (GIFImage 
*) NULL
; 
  48 //--------------------------------------------------------------------------- 
  49 // wxGIFDecoder constructor and destructor 
  50 //--------------------------------------------------------------------------- 
  52 wxGIFDecoder::wxGIFDecoder(wxInputStream 
*s
, bool anim
) 
  68 wxGIFDecoder::~wxGIFDecoder() 
  73 void wxGIFDecoder::Destroy() 
  75     GIFImage 
*pimg
, *paux
; 
  96 //--------------------------------------------------------------------------- 
  97 // Convert this image to a wxImage object 
  98 //--------------------------------------------------------------------------- 
 100 // This function was designed by Vaclav Slavik 
 102 bool wxGIFDecoder::ConvertToImage(wxImage 
*image
) const 
 104     unsigned char *src
, *dst
, *pal
; 
 108     /* just in case... */ 
 111     /* create the image */ 
 112     image
->Create(GetWidth(), GetHeight()); 
 119     dst 
= image
->GetData(); 
 120     transparent 
= GetTransparentColour(); 
 122     /* set transparent colour mask */ 
 123     if (transparent 
!= -1) 
 125         for (i 
= 0; i 
< 256; i
++) 
 127             if ((pal
[3 * i 
+ 0] == 255) && 
 128                 (pal
[3 * i 
+ 1] == 0) && 
 129                 (pal
[3 * i 
+ 2] == 255)) 
 131                 pal
[3 * i 
+ 2] = 254; 
 135         pal
[3 * transparent 
+ 0] = 255, 
 136         pal
[3 * transparent 
+ 1] = 0, 
 137         pal
[3 * transparent 
+ 2] = 255; 
 139         image
->SetMaskColour(255, 0, 255); 
 142         image
->SetMask(false); 
 147         unsigned char r
[256]; 
 148         unsigned char g
[256]; 
 149         unsigned char b
[256]; 
 151         for (i 
= 0; i 
< 256; i
++) 
 158         image
->SetPalette(wxPalette(256, r
, g
, b
)); 
 160 #endif // wxUSE_PALETTE 
 162     /* copy image data */ 
 163     for (i 
= 0; i 
< (GetWidth() * GetHeight()); i
++, src
++) 
 165         *(dst
++) = pal
[3 * (*src
) + 0]; 
 166         *(dst
++) = pal
[3 * (*src
) + 1]; 
 167         *(dst
++) = pal
[3 * (*src
) + 2]; 
 174 //--------------------------------------------------------------------------- 
 176 //--------------------------------------------------------------------------- 
 178 // Get data for current frame 
 180 int wxGIFDecoder::GetFrameIndex() const         { return m_image
; } 
 181 unsigned char* wxGIFDecoder::GetData() const    { return (m_pimage
->p
); } 
 182 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); } 
 183 unsigned int wxGIFDecoder::GetWidth() const     { return (m_pimage
->w
); } 
 184 unsigned int wxGIFDecoder::GetHeight() const    { return (m_pimage
->h
); } 
 185 unsigned int wxGIFDecoder::GetTop() const       { return (m_pimage
->top
); } 
 186 unsigned int wxGIFDecoder::GetLeft() const      { return (m_pimage
->left
); } 
 187 int wxGIFDecoder::GetTransparentColour() const  { return (m_pimage
->transparent
); } 
 188 int wxGIFDecoder::GetDisposalMethod() const     { return (m_pimage
->disposal
); } 
 189 long wxGIFDecoder::GetDelay() const             { return (m_pimage
->delay
); } 
 193 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const    { return m_screenw
; } 
 194 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const   { return m_screenh
; } 
 195 int wxGIFDecoder::GetBackgroundColour() const   { return m_background
; } 
 196 int wxGIFDecoder::GetNumberOfFrames() const     { return m_nimages
; } 
 197 bool wxGIFDecoder::IsAnimation() const          { return (m_nimages 
> 1); } 
 200 //--------------------------------------------------------------------------- 
 201 // Functions to move through the animation 
 202 //--------------------------------------------------------------------------- 
 204 bool wxGIFDecoder::GoFirstFrame() 
 214 bool wxGIFDecoder::GoLastFrame() 
 224 bool wxGIFDecoder::GoNextFrame(bool cyclic
) 
 229     if ((m_image 
< m_nimages
) || (cyclic
)) 
 231         m_pimage 
= m_pimage
->next
; 
 246 bool wxGIFDecoder::GoPrevFrame(bool cyclic
) 
 251     if ((m_image 
> 1) || (cyclic
)) 
 253         m_pimage 
= m_pimage
->prev
; 
 268 bool wxGIFDecoder::GoFrame(int which
) 
 273     if ((which 
>= 1) && (which 
<= m_nimages
)) 
 278         while (m_image 
< which
) 
 281             m_pimage 
= m_pimage
->next
; 
 291 //--------------------------------------------------------------------------- 
 292 // GIF reading and decoding 
 293 //--------------------------------------------------------------------------- 
 296 //  Reads the next code from the file stream, with size 'bits' 
 298 int wxGIFDecoder::getcode(int bits
, int ab_fin
) 
 300     unsigned int mask
;          /* bit mask */ 
 301     unsigned int code
;          /* code (result) */ 
 304     /* get remaining bits from last byte read */ 
 305     mask 
= (1 << bits
) - 1; 
 306     code 
= (m_lastbyte 
>> (8 - m_restbits
)) & mask
; 
 308     /* keep reading new bytes while needed */ 
 309     while (bits 
> m_restbits
) 
 311         /* if no bytes left in this block, read the next block */ 
 314             m_restbyte 
= (unsigned char)m_f
->GetC(); 
 316             /* Some encoders are a bit broken: instead of issuing 
 317              * an end-of-image symbol (ab_fin) they come up with 
 318              * a zero-length subblock!! We catch this here so 
 319              * that the decoder sees an ab_fin code. 
 328             m_f
->Read((void *) m_buffer
, m_restbyte
); 
 329             if (m_f
->LastRead() != m_restbyte
) 
 337         /* read next byte and isolate the bits we need */ 
 338         m_lastbyte 
= (unsigned char) (*m_bufp
++); 
 339         mask       
= (1 << (bits 
- m_restbits
)) - 1; 
 340         code       
= code 
+ ((m_lastbyte 
& mask
) << m_restbits
); 
 343         /* adjust total number of bits extracted from the buffer */ 
 344         m_restbits 
= m_restbits 
+ 8; 
 347     /* find number of bits remaining for next code */ 
 348     m_restbits 
= (m_restbits 
- bits
); 
 355 //  GIF decoding function. The initial code size (aka root size) 
 356 //  is 'bits'. Supports interlaced images (interl == 1). 
 357 //  Returns wxGIF_OK (== 0) on success, or an error code if something 
 358 // fails (see header file for details) 
 359 int wxGIFDecoder::dgif(GIFImage 
*img
, int interl
, int bits
) 
 361     static const int allocSize 
= 4096 + 1; 
 362     int *ab_prefix 
= new int[allocSize
]; /* alphabet (prefixes) */ 
 363     if (ab_prefix 
== NULL
) 
 368     int *ab_tail 
= new int[allocSize
];   /* alphabet (tails) */ 
 375     int *stack 
= new int[allocSize
];     /* decompression stack */ 
 383     int ab_clr
;                     /* clear code */ 
 384     int ab_fin
;                     /* end of info code */ 
 385     int ab_bits
;                    /* actual symbol width, in bits */ 
 386     int ab_free
;                    /* first free position in alphabet */ 
 387     int ab_max
;                     /* last possible character in alphabet */ 
 388     int pass
;                       /* pass number in interlaced images */ 
 389     int pos
;                        /* index into decompresion stack */ 
 390     unsigned int x
, y
;              /* position in image buffer */ 
 392     int code
, readcode
, lastcode
, abcabca
; 
 394     /* these won't change */ 
 395     ab_clr 
= (1 << bits
); 
 396     ab_fin 
= (1 << bits
) + 1; 
 398     /* these will change through the decompression proccess */ 
 400     ab_free  
= (1 << bits
) + 2; 
 401     ab_max   
= (1 << ab_bits
) - 1; 
 407     /* reset decoder vars */ 
 415         readcode 
= code 
= getcode(ab_bits
, ab_fin
); 
 418         if (code 
== ab_fin
) break; 
 420         /* reset alphabet? */ 
 423             /* reset main variables */ 
 425             ab_free  
= (1 << bits
) + 2; 
 426             ab_max   
= (1 << ab_bits
) - 1; 
 430             /* skip to next code */ 
 434         /* unknown code: special case (like in ABCABCA) */ 
 437             code 
= lastcode
;            /* take last string */ 
 438             stack
[pos
++] = abcabca
;     /* add first character */ 
 441         /* build the string for this code in the stack */ 
 442         while (code 
> ab_clr
) 
 444             stack
[pos
++] = ab_tail
[code
]; 
 445             code         
= ab_prefix
[code
]; 
 447             // Don't overflow. This shouldn't happen with normal 
 448             // GIF files, the allocSize of 4096+1 is enough. This 
 449             // will only happen with badly formed GIFs. 
 450             if (pos 
>= allocSize
) 
 455                 return wxGIF_INVFORMAT
; 
 459         if (pos 
>= allocSize
) 
 464             return wxGIF_INVFORMAT
; 
 467         stack
[pos
] = code
;              /* push last code into the stack */ 
 468         abcabca    
= code
;              /* save for special case */ 
 470         /* make new entry in alphabet (only if NOT just cleared) */ 
 473             ab_prefix
[ab_free
] = lastcode
; 
 474             ab_tail
[ab_free
]   = code
; 
 477             if ((ab_free 
> ab_max
) && (ab_bits 
< 12)) 
 480                 ab_max 
= (1 << ab_bits
) - 1; 
 484         /* dump stack data to the image buffer */ 
 487             (img
->p
)[x 
+ (y 
* (img
->w
))] = (char) stack
[pos
]; 
 496                     /* support for interlaced images */ 
 499                         case 1: y 
+= 8; break; 
 500                         case 2: y 
+= 8; break; 
 501                         case 3: y 
+= 4; break; 
 502                         case 4: y 
+= 2; break; 
 505                     /* loop until a valid y coordinate has been 
 506                     found, Or if the maximum number of passes has 
 507                     been reached, exit the loop, and stop image 
 508                     decoding (At this point the image is successfully 
 510                     If we don't loop, but merely set y to some other 
 511                     value, that new value might still be invalid depending 
 512                     on the height of the image. This would cause out of 
 515                     while (y 
>= (img
->h
)) 
 519                             case 2: y 
= 4; break; 
 520                             case 3: y 
= 2; break; 
 521                             case 4: y 
= 1; break; 
 525                                 It's possible we arrive here. For example this 
 526                                 happens when the image is interlaced, and the 
 527                                 height is 1. Looking at the above cases, the 
 528                                 lowest possible y is 1. While the only valid 
 529                                 one would be 0 for an image of height 1. So 
 530                                 'eventually' the loop will arrive here. 
 531                                 This case makes sure this while loop is 
 532                                 exited, as well as the 2 other ones. 
 535                                 // Set y to a valid coordinate so the local 
 536                                 // while loop will be exited. (y = 0 always 
 537                                 // is >= img->h since if img->h == 0 the 
 538                                 // image is never decoded) 
 541                                 // This will exit the other outer while loop 
 544                                 // This will halt image decoding. 
 556 Normally image decoding is finished when an End of Information code is 
 557 encountered (code == ab_fin) however some broken encoders write wrong 
 558 "block byte counts" (The first byte value after the "code size" byte), 
 559 being one value too high. It might very well be possible other variants 
 560 of this problem occur as well. The only sensible solution seems to 
 561 be to check for clipping. 
 562 Example of wrong encoding: 
 563 (1 * 1 B/W image, raster data stream follows in hex bytes) 
 565 02  << B/W images have a code size of 2 
 566 02  << Block byte count 
 568 00  << Zero byte count (terminates data stream) 
 570 Because the block byte count is 2, the zero byte count is used in the 
 571 decoding process, and decoding is continued after this byte. (While it 
 572 should signal an end of image) 
 578 01  << When decoded this correctly includes the End of Information code 
 586 (The 44 doesn't include an End of Information code, but at least the 
 587 decoder correctly skips to 00 now after decoding, and signals this 
 588 as an End of Information itself) 
 602     while (code 
!= ab_fin
); 
 604     delete [] ab_prefix 
; 
 613 //  Returns true if the file looks like a valid GIF, false otherwise. 
 615 bool wxGIFDecoder::CanRead() 
 617     unsigned char buf
[3]; 
 619     if ( !m_f
->Read(buf
, WXSIZEOF(buf
)) ) 
 622     m_f
->SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
); 
 624     return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0; 
 629 //  Reads and decodes one or more GIF images, depending on whether 
 630 //  animated GIF support is enabled. Can read GIFs with any bit 
 631 //  size (color depth), but the output images are always expanded 
 632 //  to 8 bits per pixel. Also, the image palettes always contain 
 633 //  256 colors, although some of them may be unused. Returns wxGIF_OK 
 634 //  (== 0) on success, or an error code if something fails (see 
 635 //  header file for details) 
 637 int wxGIFDecoder::ReadGIF() 
 639     unsigned int ncolors
; 
 640     int           bits
, interl
, transparent
, disposal
, i
; 
 643     unsigned char type 
= 0; 
 644     unsigned char pal
[768]; 
 645     unsigned char buf
[16]; 
 647     GIFImage      
*pimg
, *pprev
; 
 649     /* check GIF signature */ 
 651         return wxGIF_INVFORMAT
; 
 653     /* check for animated GIF support (ver. >= 89a) */ 
 655     static const size_t headerSize 
= (3 + 3); 
 656     m_f
->Read(buf
, headerSize
); 
 657     if (m_f
->LastRead() != headerSize
) 
 659         return wxGIF_INVFORMAT
; 
 662     if (memcmp(buf 
+ 3, "89a", 3) < 0) 
 667     /* read logical screen descriptor block (LSDB) */ 
 668     static const size_t lsdbSize 
= (2 + 2 + 1 + 1 + 1); 
 669     m_f
->Read(buf
, lsdbSize
); 
 670     if (m_f
->LastRead() != lsdbSize
) 
 672         return wxGIF_INVFORMAT
; 
 675     m_screenw 
= buf
[0] + 256 * buf
[1]; 
 676     m_screenh 
= buf
[2] + 256 * buf
[3]; 
 678     if ((m_screenw 
== 0) || (m_screenh 
== 0)) 
 680         return wxGIF_INVFORMAT
; 
 683     /* load global color map if available */ 
 684     if ((buf
[4] & 0x80) == 0x80) 
 686         m_background 
= buf
[5]; 
 688         ncolors 
= 2 << (buf
[4] & 0x07); 
 689         size_t numBytes 
= 3 * ncolors
; 
 690         m_f
->Read(pal
, numBytes
); 
 691         if (m_f
->LastRead() != numBytes
) 
 693             return wxGIF_INVFORMAT
; 
 697     /* transparent colour, disposal method and delay default to unused */ 
 711         type 
= (unsigned char)m_f
->GetC(); 
 714         If the end of file has been reached (or an error) and a ";" 
 715         (0x3B) hasn't been encountered yet, exit the loop. (Without this 
 716         check the while loop would loop endlessly.) Later on, in the next while 
 717         loop, the file will be treated as being truncated (But still 
 718         be decoded as far as possible). returning wxGIF_TRUNCATED is not 
 719         possible here since some init code is done after this loop. 
 721         if (m_f
->Eof())// || !m_f->IsOk()) 
 724             type is set to some bogus value, so there's no 
 725             need to continue evaluating it. 
 727             break; // Alternative : "return wxGIF_INVFORMAT;" 
 736         /* extension block? */ 
 739             if (((unsigned char)m_f
->GetC()) == 0xF9) 
 740             /* graphics control extension, parse it */ 
 742                 static const size_t gceSize 
= 6; 
 743                 m_f
->Read(buf
, gceSize
); 
 744                 if (m_f
->LastRead() != gceSize
) 
 747                     return wxGIF_INVFORMAT
; 
 750                 /* read delay and convert from 1/100 of a second to ms */ 
 751                 delay 
= 10 * (buf
[2] + 256 * buf
[3]); 
 753                 /* read transparent colour index, if used */ 
 755                     transparent 
= buf
[4]; 
 757                 /* read disposal method */ 
 758                 disposal 
= ((buf
[1] & 0x1C) >> 2) - 1; 
 761             /* other extension, skip */ 
 763                 while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 765                     m_f
->SeekI(i
, wxFromCurrent
); 
 775         /* image descriptor block? */ 
 778             /* allocate memory for IMAGEN struct */ 
 779             pimg 
= (*ppimg
) = new GIFImage(); 
 787             /* fill in the data */ 
 788             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 789             m_f
->Read(buf
, idbSize
); 
 790             if (m_f
->LastRead() != idbSize
) 
 793                 return wxGIF_INVFORMAT
; 
 796             pimg
->left 
= buf
[0] + 256 * buf
[1]; 
 797             pimg
->top 
= buf
[2] + 256 * buf
[3]; 
 799             pimg->left = buf[4] + 256 * buf[5]; 
 800             pimg->top = buf[4] + 256 * buf[5]; 
 802             pimg
->w 
= buf
[4] + 256 * buf
[5]; 
 803             pimg
->h 
= buf
[6] + 256 * buf
[7]; 
 805             if ((pimg
->w 
== 0) || (pimg
->w 
> m_screenw
) || (pimg
->h 
== 0) || (pimg
->h 
> m_screenh
)) 
 808                 return wxGIF_INVFORMAT
; 
 811             interl 
= ((buf
[8] & 0x40)? 1 : 0); 
 812             size 
= pimg
->w 
* pimg
->h
; 
 814             pimg
->transparent 
= transparent
; 
 815             pimg
->disposal 
= disposal
; 
 822             /* allocate memory for image and palette */ 
 823             pimg
->p   
= (unsigned char *) malloc((size_t)size
); 
 824             pimg
->pal 
= (unsigned char *) malloc(768); 
 826             if ((!pimg
->p
) || (!pimg
->pal
)) 
 832             /* load local color map if available, else use global map */ 
 833             if ((buf
[8] & 0x80) == 0x80) 
 835                 ncolors 
= 2 << (buf
[8] & 0x07); 
 836                 size_t numBytes 
= 3 * ncolors
; 
 837                 m_f
->Read(pimg
->pal
, numBytes
); 
 838                 if (m_f
->LastRead() != numBytes
) 
 841                     return wxGIF_INVFORMAT
; 
 846                 memcpy(pimg
->pal
, pal
, 768); 
 849             /* get initial code size from first byte in raster data */ 
 850             bits 
= (unsigned char)m_f
->GetC(); 
 854                 return wxGIF_INVFORMAT
; 
 858             int result 
= dgif(pimg
, interl
, bits
); 
 859             if (result 
!= wxGIF_OK
) 
 866             /* if this is not an animated GIF, exit after first image */ 
 875         return wxGIF_INVFORMAT
; 
 878     /* setup image pointers */ 
 883     /* try to read to the end of the stream */ 
 887             return wxGIF_TRUNCATED
; 
 889         type 
= (unsigned char)m_f
->GetC(); 
 897             while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 899                 m_f
->SeekI(i
, wxFromCurrent
); 
 902         else if (type 
== 0x2C) 
 904             /* image descriptor block */ 
 905             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 906             m_f
->Read(buf
, idbSize
); 
 907             if (m_f
->LastRead() != idbSize
) 
 910                 return wxGIF_INVFORMAT
; 
 913             /* local color map */ 
 914             if ((buf
[8] & 0x80) == 0x80) 
 916                 ncolors 
= 2 << (buf
[8] & 0x07); 
 917                 wxFileOffset pos 
= m_f
->TellI(); 
 918                 wxFileOffset numBytes 
= 3 * ncolors
; 
 919                 m_f
->SeekI(numBytes
, wxFromCurrent
); 
 920                 if (m_f
->TellI() != (pos 
+ numBytes
)) 
 923                     return wxGIF_INVFORMAT
; 
 927             /* initial code size */ 
 931             while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 933                 m_f
->SeekI(i
, wxFromCurrent
); 
 936         else if ((type 
!= 0x3B) && (type 
!= 00)) /* testing */ 
 938             /* images are OK, but couldn't read to the end of the stream */ 
 939             return wxGIF_TRUNCATED
; 
 946 #endif // wxUSE_STREAMS && wxUSE_GIF