]>
git.saurik.com Git - wxWidgets.git/blob - src/common/gifdecod.cpp
8fda5f8ae137b2588d566077a4547b08500aac49
   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); 
 145     unsigned char r
[256]; 
 146     unsigned char g
[256]; 
 147     unsigned char b
[256]; 
 149     for (i 
= 0; i 
< 256; i
++) 
 156     image
->SetPalette(wxPalette(256, r
, g
, b
)); 
 157 #endif // wxUSE_PALETTE 
 159     /* copy image data */ 
 160     for (i 
= 0; i 
< (GetWidth() * GetHeight()); i
++, src
++) 
 162         *(dst
++) = pal
[3 * (*src
) + 0]; 
 163         *(dst
++) = pal
[3 * (*src
) + 1]; 
 164         *(dst
++) = pal
[3 * (*src
) + 2]; 
 171 //--------------------------------------------------------------------------- 
 173 //--------------------------------------------------------------------------- 
 175 // Get data for current frame 
 177 int wxGIFDecoder::GetFrameIndex() const         { return m_image
; } 
 178 unsigned char* wxGIFDecoder::GetData() const    { return (m_pimage
->p
); } 
 179 unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage
->pal
); } 
 180 unsigned int wxGIFDecoder::GetWidth() const     { return (m_pimage
->w
); } 
 181 unsigned int wxGIFDecoder::GetHeight() const    { return (m_pimage
->h
); } 
 182 unsigned int wxGIFDecoder::GetTop() const       { return (m_pimage
->top
); } 
 183 unsigned int wxGIFDecoder::GetLeft() const      { return (m_pimage
->left
); } 
 184 int wxGIFDecoder::GetTransparentColour() const  { return (m_pimage
->transparent
); } 
 185 int wxGIFDecoder::GetDisposalMethod() const     { return (m_pimage
->disposal
); } 
 186 long wxGIFDecoder::GetDelay() const             { return (m_pimage
->delay
); } 
 190 unsigned int wxGIFDecoder::GetLogicalScreenWidth() const    { return m_screenw
; } 
 191 unsigned int wxGIFDecoder::GetLogicalScreenHeight() const   { return m_screenh
; } 
 192 int wxGIFDecoder::GetBackgroundColour() const   { return m_background
; } 
 193 int wxGIFDecoder::GetNumberOfFrames() const     { return m_nimages
; } 
 194 bool wxGIFDecoder::IsAnimation() const          { return (m_nimages 
> 1); } 
 197 //--------------------------------------------------------------------------- 
 198 // Functions to move through the animation 
 199 //--------------------------------------------------------------------------- 
 201 bool wxGIFDecoder::GoFirstFrame() 
 211 bool wxGIFDecoder::GoLastFrame() 
 221 bool wxGIFDecoder::GoNextFrame(bool cyclic
) 
 226     if ((m_image 
< m_nimages
) || (cyclic
)) 
 228         m_pimage 
= m_pimage
->next
; 
 243 bool wxGIFDecoder::GoPrevFrame(bool cyclic
) 
 248     if ((m_image 
> 1) || (cyclic
)) 
 250         m_pimage 
= m_pimage
->prev
; 
 265 bool wxGIFDecoder::GoFrame(int which
) 
 270     if ((which 
>= 1) && (which 
<= m_nimages
)) 
 275         while (m_image 
< which
) 
 278             m_pimage 
= m_pimage
->next
; 
 288 //--------------------------------------------------------------------------- 
 289 // GIF reading and decoding 
 290 //--------------------------------------------------------------------------- 
 293 //  Reads the next code from the file stream, with size 'bits' 
 295 int wxGIFDecoder::getcode(int bits
, int ab_fin
) 
 297     unsigned int mask
;          /* bit mask */ 
 298     unsigned int code
;          /* code (result) */ 
 301     /* get remaining bits from last byte read */ 
 302     mask 
= (1 << bits
) - 1; 
 303     code 
= (m_lastbyte 
>> (8 - m_restbits
)) & mask
; 
 305     /* keep reading new bytes while needed */ 
 306     while (bits 
> m_restbits
) 
 308         /* if no bytes left in this block, read the next block */ 
 311             m_restbyte 
= (unsigned char)m_f
->GetC(); 
 313             /* Some encoders are a bit broken: instead of issuing 
 314              * an end-of-image symbol (ab_fin) they come up with 
 315              * a zero-length subblock!! We catch this here so 
 316              * that the decoder sees an ab_fin code. 
 325             m_f
->Read((void *) m_buffer
, m_restbyte
); 
 326             if (m_f
->LastRead() != m_restbyte
) 
 334         /* read next byte and isolate the bits we need */ 
 335         m_lastbyte 
= (unsigned char) (*m_bufp
++); 
 336         mask       
= (1 << (bits 
- m_restbits
)) - 1; 
 337         code       
= code 
+ ((m_lastbyte 
& mask
) << m_restbits
); 
 340         /* adjust total number of bits extracted from the buffer */ 
 341         m_restbits 
= m_restbits 
+ 8; 
 344     /* find number of bits remaining for next code */ 
 345     m_restbits 
= (m_restbits 
- bits
); 
 352 //  GIF decoding function. The initial code size (aka root size) 
 353 //  is 'bits'. Supports interlaced images (interl == 1). 
 354 //  Returns wxGIF_OK (== 0) on success, or an error code if something 
 355 // fails (see header file for details) 
 356 int wxGIFDecoder::dgif(GIFImage 
*img
, int interl
, int bits
) 
 358     static const int allocSize 
= 4096 + 1; 
 359     int *ab_prefix 
= new int[allocSize
]; /* alphabet (prefixes) */ 
 360     if (ab_prefix 
== NULL
) 
 365     int *ab_tail 
= new int[allocSize
];   /* alphabet (tails) */ 
 372     int *stack 
= new int[allocSize
];     /* decompression stack */ 
 380     int ab_clr
;                     /* clear code */ 
 381     int ab_fin
;                     /* end of info code */ 
 382     int ab_bits
;                    /* actual symbol width, in bits */ 
 383     int ab_free
;                    /* first free position in alphabet */ 
 384     int ab_max
;                     /* last possible character in alphabet */ 
 385     int pass
;                       /* pass number in interlaced images */ 
 386     int pos
;                        /* index into decompresion stack */ 
 387     unsigned int x
, y
;              /* position in image buffer */ 
 389     int code
, readcode
, lastcode
, abcabca
; 
 391     /* these won't change */ 
 392     ab_clr 
= (1 << bits
); 
 393     ab_fin 
= (1 << bits
) + 1; 
 395     /* these will change through the decompression proccess */ 
 397     ab_free  
= (1 << bits
) + 2; 
 398     ab_max   
= (1 << ab_bits
) - 1; 
 404     /* reset decoder vars */ 
 412         readcode 
= code 
= getcode(ab_bits
, ab_fin
); 
 415         if (code 
== ab_fin
) break; 
 417         /* reset alphabet? */ 
 420             /* reset main variables */ 
 422             ab_free  
= (1 << bits
) + 2; 
 423             ab_max   
= (1 << ab_bits
) - 1; 
 427             /* skip to next code */ 
 431         /* unknown code: special case (like in ABCABCA) */ 
 434             code 
= lastcode
;            /* take last string */ 
 435             stack
[pos
++] = abcabca
;     /* add first character */ 
 438         /* build the string for this code in the stack */ 
 439         while (code 
> ab_clr
) 
 441             stack
[pos
++] = ab_tail
[code
]; 
 442             code         
= ab_prefix
[code
]; 
 444             // Don't overflow. This shouldn't happen with normal 
 445             // GIF files, the allocSize of 4096+1 is enough. This 
 446             // will only happen with badly formed GIFs. 
 447             if (pos 
>= allocSize
) 
 452                 return wxGIF_INVFORMAT
; 
 456         if (pos 
>= allocSize
) 
 461             return wxGIF_INVFORMAT
; 
 464         stack
[pos
] = code
;              /* push last code into the stack */ 
 465         abcabca    
= code
;              /* save for special case */ 
 467         /* make new entry in alphabet (only if NOT just cleared) */ 
 470             ab_prefix
[ab_free
] = lastcode
; 
 471             ab_tail
[ab_free
]   = code
; 
 474             if ((ab_free 
> ab_max
) && (ab_bits 
< 12)) 
 477                 ab_max 
= (1 << ab_bits
) - 1; 
 481         /* dump stack data to the image buffer */ 
 484             (img
->p
)[x 
+ (y 
* (img
->w
))] = (char) stack
[pos
]; 
 493                     /* support for interlaced images */ 
 496                         case 1: y 
+= 8; break; 
 497                         case 2: y 
+= 8; break; 
 498                         case 3: y 
+= 4; break; 
 499                         case 4: y 
+= 2; break; 
 502                     /* loop until a valid y coordinate has been 
 503                     found, Or if the maximum number of passes has 
 504                     been reached, exit the loop, and stop image 
 505                     decoding (At this point the image is successfully 
 507                     If we don't loop, but merely set y to some other 
 508                     value, that new value might still be invalid depending 
 509                     on the height of the image. This would cause out of 
 512                     while (y 
>= (img
->h
)) 
 516                             case 2: y 
= 4; break; 
 517                             case 3: y 
= 2; break; 
 518                             case 4: y 
= 1; break; 
 522                                 It's possible we arrive here. For example this 
 523                                 happens when the image is interlaced, and the 
 524                                 height is 1. Looking at the above cases, the 
 525                                 lowest possible y is 1. While the only valid 
 526                                 one would be 0 for an image of height 1. So 
 527                                 'eventually' the loop will arrive here. 
 528                                 This case makes sure this while loop is 
 529                                 exited, as well as the 2 other ones. 
 532                                 // Set y to a valid coordinate so the local 
 533                                 // while loop will be exited. (y = 0 always 
 534                                 // is >= img->h since if img->h == 0 the 
 535                                 // image is never decoded) 
 538                                 // This will exit the other outer while loop 
 541                                 // This will halt image decoding. 
 553 Normally image decoding is finished when an End of Information code is 
 554 encountered (code == ab_fin) however some broken encoders write wrong 
 555 "block byte counts" (The first byte value after the "code size" byte), 
 556 being one value too high. It might very well be possible other variants 
 557 of this problem occur as well. The only sensible solution seems to 
 558 be to check for clipping. 
 559 Example of wrong encoding: 
 560 (1 * 1 B/W image, raster data stream follows in hex bytes) 
 562 02  << B/W images have a code size of 2 
 563 02  << Block byte count 
 565 00  << Zero byte count (terminates data stream) 
 567 Because the block byte count is 2, the zero byte count is used in the 
 568 decoding process, and decoding is continued after this byte. (While it 
 569 should signal an end of image) 
 575 01  << When decoded this correctly includes the End of Information code 
 583 (The 44 doesn't include an End of Information code, but at least the 
 584 decoder correctly skips to 00 now after decoding, and signals this 
 585 as an End of Information itself) 
 599     while (code 
!= ab_fin
); 
 601     delete [] ab_prefix 
; 
 610 //  Returns true if the file looks like a valid GIF, false otherwise. 
 612 bool wxGIFDecoder::CanRead() 
 614     unsigned char buf
[3]; 
 616     if ( !m_f
->Read(buf
, WXSIZEOF(buf
)) ) 
 619     m_f
->SeekI(-(wxFileOffset
)WXSIZEOF(buf
), wxFromCurrent
); 
 621     return memcmp(buf
, "GIF", WXSIZEOF(buf
)) == 0; 
 626 //  Reads and decodes one or more GIF images, depending on whether 
 627 //  animated GIF support is enabled. Can read GIFs with any bit 
 628 //  size (color depth), but the output images are always expanded 
 629 //  to 8 bits per pixel. Also, the image palettes always contain 
 630 //  256 colors, although some of them may be unused. Returns wxGIF_OK 
 631 //  (== 0) on success, or an error code if something fails (see 
 632 //  header file for details) 
 634 int wxGIFDecoder::ReadGIF() 
 636     unsigned int ncolors
; 
 637     int           bits
, interl
, transparent
, disposal
, i
; 
 640     unsigned char type 
= 0; 
 641     unsigned char pal
[768]; 
 642     unsigned char buf
[16]; 
 644     GIFImage      
*pimg
, *pprev
; 
 646     /* check GIF signature */ 
 648         return wxGIF_INVFORMAT
; 
 650     /* check for animated GIF support (ver. >= 89a) */ 
 652     static const size_t headerSize 
= (3 + 3); 
 653     m_f
->Read(buf
, headerSize
); 
 654     if (m_f
->LastRead() != headerSize
) 
 656         return wxGIF_INVFORMAT
; 
 659     if (memcmp(buf 
+ 3, "89a", 3) < 0) 
 664     /* read logical screen descriptor block (LSDB) */ 
 665     static const size_t lsdbSize 
= (2 + 2 + 1 + 1 + 1); 
 666     m_f
->Read(buf
, lsdbSize
); 
 667     if (m_f
->LastRead() != lsdbSize
) 
 669         return wxGIF_INVFORMAT
; 
 672     m_screenw 
= buf
[0] + 256 * buf
[1]; 
 673     m_screenh 
= buf
[2] + 256 * buf
[3]; 
 675     if ((m_screenw 
== 0) || (m_screenh 
== 0)) 
 677         return wxGIF_INVFORMAT
; 
 680     /* load global color map if available */ 
 681     if ((buf
[4] & 0x80) == 0x80) 
 683         m_background 
= buf
[5]; 
 685         ncolors 
= 2 << (buf
[4] & 0x07); 
 686         size_t numBytes 
= 3 * ncolors
; 
 687         m_f
->Read(pal
, numBytes
); 
 688         if (m_f
->LastRead() != numBytes
) 
 690             return wxGIF_INVFORMAT
; 
 694     /* transparent colour, disposal method and delay default to unused */ 
 708         type 
= (unsigned char)m_f
->GetC(); 
 711         If the end of file has been reached (or an error) and a ";" 
 712         (0x3B) hasn't been encountered yet, exit the loop. (Without this 
 713         check the while loop would loop endlessly.) Later on, in the next while 
 714         loop, the file will be treated as being truncated (But still 
 715         be decoded as far as possible). returning wxGIF_TRUNCATED is not 
 716         possible here since some init code is done after this loop. 
 718         if (m_f
->Eof())// || !m_f->IsOk()) 
 721             type is set to some bogus value, so there's no 
 722             need to continue evaluating it. 
 724             break; // Alternative : "return wxGIF_INVFORMAT;" 
 733         /* extension block? */ 
 736             if (((unsigned char)m_f
->GetC()) == 0xF9) 
 737             /* graphics control extension, parse it */ 
 739                 static const size_t gceSize 
= 6; 
 740                 m_f
->Read(buf
, gceSize
); 
 741                 if (m_f
->LastRead() != gceSize
) 
 744                     return wxGIF_INVFORMAT
; 
 747                 /* read delay and convert from 1/100 of a second to ms */ 
 748                 delay 
= 10 * (buf
[2] + 256 * buf
[3]); 
 750                 /* read transparent colour index, if used */ 
 752                     transparent 
= buf
[4]; 
 754                 /* read disposal method */ 
 755                 disposal 
= ((buf
[1] & 0x1C) >> 2) - 1; 
 758             /* other extension, skip */ 
 760                 while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 762                     m_f
->SeekI(i
, wxFromCurrent
); 
 772         /* image descriptor block? */ 
 775             /* allocate memory for IMAGEN struct */ 
 776             pimg 
= (*ppimg
) = new GIFImage(); 
 784             /* fill in the data */ 
 785             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 786             m_f
->Read(buf
, idbSize
); 
 787             if (m_f
->LastRead() != idbSize
) 
 790                 return wxGIF_INVFORMAT
; 
 793             pimg
->left 
= buf
[0] + 256 * buf
[1]; 
 794             pimg
->top 
= buf
[2] + 256 * buf
[3]; 
 796             pimg->left = buf[4] + 256 * buf[5]; 
 797             pimg->top = buf[4] + 256 * buf[5]; 
 799             pimg
->w 
= buf
[4] + 256 * buf
[5]; 
 800             pimg
->h 
= buf
[6] + 256 * buf
[7]; 
 802             if ((pimg
->w 
== 0) || (pimg
->w 
> m_screenw
) || (pimg
->h 
== 0) || (pimg
->h 
> m_screenh
)) 
 805                 return wxGIF_INVFORMAT
; 
 808             interl 
= ((buf
[8] & 0x40)? 1 : 0); 
 809             size 
= pimg
->w 
* pimg
->h
; 
 811             pimg
->transparent 
= transparent
; 
 812             pimg
->disposal 
= disposal
; 
 819             /* allocate memory for image and palette */ 
 820             pimg
->p   
= (unsigned char *) malloc((size_t)size
); 
 821             pimg
->pal 
= (unsigned char *) malloc(768); 
 823             if ((!pimg
->p
) || (!pimg
->pal
)) 
 829             /* load local color map if available, else use global map */ 
 830             if ((buf
[8] & 0x80) == 0x80) 
 832                 ncolors 
= 2 << (buf
[8] & 0x07); 
 833                 size_t numBytes 
= 3 * ncolors
; 
 834                 m_f
->Read(pimg
->pal
, numBytes
); 
 835                 if (m_f
->LastRead() != numBytes
) 
 838                     return wxGIF_INVFORMAT
; 
 843                 memcpy(pimg
->pal
, pal
, 768); 
 846             /* get initial code size from first byte in raster data */ 
 847             bits 
= (unsigned char)m_f
->GetC(); 
 851                 return wxGIF_INVFORMAT
; 
 855             int result 
= dgif(pimg
, interl
, bits
); 
 856             if (result 
!= wxGIF_OK
) 
 863             /* if this is not an animated GIF, exit after first image */ 
 872         return wxGIF_INVFORMAT
; 
 875     /* setup image pointers */ 
 880     /* try to read to the end of the stream */ 
 884             return wxGIF_TRUNCATED
; 
 886         type 
= (unsigned char)m_f
->GetC(); 
 894             while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 896                 m_f
->SeekI(i
, wxFromCurrent
); 
 899         else if (type 
== 0x2C) 
 901             /* image descriptor block */ 
 902             static const size_t idbSize 
= (2 + 2 + 2 + 2 + 1); 
 903             m_f
->Read(buf
, idbSize
); 
 904             if (m_f
->LastRead() != idbSize
) 
 907                 return wxGIF_INVFORMAT
; 
 910             /* local color map */ 
 911             if ((buf
[8] & 0x80) == 0x80) 
 913                 ncolors 
= 2 << (buf
[8] & 0x07); 
 914                 wxFileOffset pos 
= m_f
->TellI(); 
 915                 wxFileOffset numBytes 
= 3 * ncolors
; 
 916                 m_f
->SeekI(numBytes
, wxFromCurrent
); 
 917                 if (m_f
->TellI() != (pos 
+ numBytes
)) 
 920                     return wxGIF_INVFORMAT
; 
 924             /* initial code size */ 
 928             while ((i 
= (unsigned char)m_f
->GetC()) != 0) 
 930                 m_f
->SeekI(i
, wxFromCurrent
); 
 933         else if ((type 
!= 0x3B) && (type 
!= 00)) /* testing */ 
 935             /* images are OK, but couldn't read to the end of the stream */ 
 936             return wxGIF_TRUNCATED
; 
 943 #endif // wxUSE_STREAMS && wxUSE_GIF