]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imaggif.cpp
596c9932d5d5f2929bef3d160f75f962c937d7ad
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxGIFHandler 
   4 // Author:      Guillermo Rodriguez Garcia 
   5 //              wxWindows adaptation by Vaclav Slavik 
   6 // Licence:     wxWindows licence 
   7 ///////////////////////////////////////////////////////////////////////////// 
  10 #pragma implementation "imaggif.h" 
  13 // For compilers that support precompilation, includes "wx.h". 
  14 #include <wx/wxprec.h> 
  23 #include <wx/wfstream.h> 
  24 #include <wx/module.h> 
  26 #include <wx/imaggif.h> 
  30 FOLLOWING CODE IS BY G.R.G. : 
  31 (except wxInputStream stuff) 
  35 /************************************************************************ 
  36   READGIF.H - Reads a GIF file 
  37  ------------------------------------------------------------------------ 
  38   Guillermo Rodriguez Garcia 
  42 *************************************************************************/ 
  49     int transparent
;        /* transparent color (-1 = none) */ 
  50     unsigned char *p
;       /* bitmap */ 
  51     unsigned char *pal
;     /* palette */ 
  56 /************************************************************************ 
  57   READGIF.C - Reads a GIF file 
  58  ------------------------------------------------------------------------ 
  59   Guillermo Rodriguez Garcia 
  63 *************************************************************************/ 
  71 #define E_OK        0               /* everything was OK */ 
  72 #define E_ARCHIVO   -1              /* error opening file */ 
  73 #define E_FORMATO   -2              /* error in gif header */ 
  74 #define E_MEMORIA   -3              /* error allocating memory */ 
  77 /* This class binding is by VS, so all bugs in it are mine ;-) */ 
  83         int            restbits
;            /* remaining valid bits */ 
  84         unsigned int   restbyte
;            /* remaining bytes in this block */ 
  85         unsigned int   lastbyte
;            /* last byte read */ 
  87         wxInputStream  
*f
;                  /* input file */ 
  90                 gifDecoder(wxInputStream 
*s
) { f 
= s
; } 
  91                 int getcode(int bits
); 
  92                 int dgif(IMAGEN 
*img
, int interl
, int bits
); 
  93                 int readgif(IMAGEN 
*img
); 
  99  *  Reads the next code from the file, with size 'bits' 
 101 int gifDecoder::getcode(int bits
) 
 103     unsigned int    mask
;           /* bit mask */ 
 104     unsigned int    code
;           /* code (result) */ 
 107     /* get remaining bits from last byte read */ 
 108     mask 
= (1 << bits
) - 1; 
 109     code 
= (lastbyte 
>> (8 - restbits
)) & mask
; 
 111     /* keep reading new bytes while needed */ 
 112     while (bits 
> restbits
) 
 114         /* if no bytes left in this block, read the next block */ 
 116             restbyte 
= (unsigned char)f
->GetC(); 
 118         /* read next byte and isolate the bits we need */ 
 119         lastbyte 
= (unsigned char)f
->GetC(); 
 120         mask     
= (1 << (bits 
- restbits
)) - 1; 
 121         code     
= code 
+ ((lastbyte 
& mask
) << restbits
); 
 124         /* adjust total number of bits extracted from the buffer */ 
 125         restbits 
= restbits 
+ 8; 
 128     /* find number of bits reamining for next code */ 
 129     restbits 
= (restbits 
- bits
); 
 137  *  GIF decoding function. The initial code size (aka root size) 
 138  *  is 'bits'. Supports interlaced images (interl == 1). 
 140 int gifDecoder::dgif(IMAGEN 
*img
, int interl
, int bits
) 
 142     int ab_prefix
[4096];        /* alphabet (prefixes) */ 
 143     int ab_tail
[4096];          /* alphabet (tails) */ 
 144     int stack
[4096];            /* decompression stack */ 
 146     int ab_clr
;                 /* clear code */ 
 147     int ab_fin
;                 /* end of info code */ 
 148     int ab_bits
;                /* actual symbol width, in bits */ 
 149     int ab_free
;                /* first free position in alphabet */ 
 150     int ab_max
;                 /* last possible character in alphabet */ 
 151     int pass
;                   /* pass number in interlaced images */ 
 152     int pos
;                    /* index into decompresion stack */ 
 153     int x
, y
;                   /* position in image buffer */ 
 155     int code
, readcode
, lastcode
, abcabca
; 
 157     /* these won't change */ 
 158     ab_clr  
= (1 << bits
); 
 159     ab_fin  
= (1 << bits
) + 1; 
 161     /* these will change through the decompression proccess */ 
 163     ab_free  
= (1 << bits
) + 2; 
 164     ab_max   
= (1 << ab_bits
) - 1; 
 170     /* reset static globals */ 
 178         readcode 
= code 
= getcode(ab_bits
); 
 181         if (code 
== ab_fin
) break; 
 183         /* reset alphabet? */ 
 186             /* reset main variables */ 
 188             ab_free  
= (1 << bits
) + 2; 
 189             ab_max   
= (1 << ab_bits
) - 1; 
 193             /* skip to next code */ 
 197         /* unknown code: special case (like in ABCABCA) */ 
 200             code 
= lastcode
;            /* take last string */ 
 201             stack
[pos
++] = abcabca
;     /* add first character */ 
 204         /* build the string for this code in the stack */ 
 205         while (code 
> ab_clr
) 
 207             stack
[pos
++] = ab_tail
[code
]; 
 208             code         
= ab_prefix
[code
]; 
 210         stack
[pos
] = code
;              /* push last code into the stack */ 
 211         abcabca    
= code
;              /* save for special case */ 
 213         /* make new entry in alphabet (only if NOT just cleared) */ 
 216             ab_prefix
[ab_free
] = lastcode
; 
 217             ab_tail
[ab_free
]   = code
; 
 220             if ((ab_free 
> ab_max
) && (ab_bits 
< 12)) 
 223                 ab_max 
= (1 << ab_bits
) - 1; 
 227         /* dump stack data to the buffer */ 
 230             (img
->p
)[x 
+ (y 
* (img
->w
))] = (char)stack
[pos
--]; 
 238                     /* support for interlaced images */ 
 241                         case 1: y 
+= 8; break; 
 242                         case 2: y 
+= 8; break; 
 243                         case 3: y 
+= 4; break; 
 244                         case 4: y 
+= 2; break; 
 250                             case 2: y 
= 4; break; 
 251                             case 3: y 
= 2; break; 
 252                             case 4: y 
= 1; break; 
 267     while (code 
!= ab_fin
); 
 275  *  Reads a GIF image from the file with filename 'nombre' in the 
 276  *  IMAGEN structure pointed by 'img'. Can read GIFs with any bit 
 277  *  size (color depth), but the output image is always expanded 
 278  *  to 8 bits per pixel. Also, the image palette always contains 
 279  *  256 colors, although some of them may be unused. Returns E_OK 
 280  *  (== 0) on success, or an error code if something fails. Error 
 281  *  codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see above). 
 283 int gifDecoder::readgif(IMAGEN 
*img
) 
 285     int             size
, ncolors
, bits
, interl
, i
; 
 286     unsigned char   pal
[768]; 
 287     unsigned char   buf
[16]; 
 290     /* read header and logical screen descriptor block (LSDB) */ 
 293     /* check GIF signature */ 
 294     if (memcmp(buf
, "GIF", 3) != 0) return E_FORMATO
; 
 296     /* load global color map if available */ 
 297     if ((buf
[10] & 0x80) == 0x80) 
 299         ncolors 
= 2 << (buf
[10] & 0x07); 
 300         f
->Read(pal
, 3 * ncolors
); 
 303     /* assume no transparent color */ 
 304     img
->transparent 
= -1; 
 306     /* skip most extensions */ 
 307     while (((unsigned char)f
->GetC()) == 0x21)               /* separator */ 
 309         if (((unsigned char)f
->GetC()) == 0xF9)              /* graphic control ext. */ 
 313                 img
->transparent 
= buf
[4]; 
 316             while ((i 
= (unsigned char)f
->GetC()) != 0)    /* byte count */ 
 317                 f
->SeekI(i
, wxFromCurrent
); 
 320     /* read image descriptor block (IDB) */ 
 322     img
->w 
= buf
[4] + 256 * buf
[5]; 
 323     img
->h 
= buf
[6] + 256 * buf
[7]; 
 324     size   
= img
->w 
* img
->h
; 
 325     interl 
= ((buf
[8] & 0x40)? 1 : 0); 
 327     /* load local color map if available */ 
 328     if ((buf
[8] & 0x80) == 0x80) 
 330         ncolors 
= 2 << (buf
[8] & 0x07); 
 331         f
->Read(pal
, 3 * ncolors
); 
 334     /* get initial code size from first byte in raster data */ 
 335     bits 
= (unsigned char)f
->GetC(); 
 337     /* allocate memory for image and palette */ 
 338     if ((img
->p   
= (unsigned char*) malloc(size
)) == NULL
) return E_MEMORIA
; 
 339     if ((img
->pal 
= (unsigned char*) malloc(768))  == NULL
) return E_MEMORIA
; 
 341     /* shift palette to fit VGA 6-bit format */ 
 342     for (i 
= 0; i 
< 768; i
++) 
 343         (img
->pal
)[i
] = (unsigned char)pal
[i
]; /* >> 2 not in wxWin */ 
 346     dgif(img
, interl
, bits
); 
 348     /* finish successfully :-) */ 
 356 FOLLOWING CODE IS BY V.S. : 
 360 //----------------------------------------------------------------------------- 
 362 //----------------------------------------------------------------------------- 
 364 IMPLEMENT_DYNAMIC_CLASS(wxGIFHandler
,wxImageHandler
) 
 366 bool wxGIFHandler::LoadFile( wxImage 
*image
, wxInputStream
& stream 
) 
 368     unsigned char *ptr
, *src
, *pal
; 
 375     decod 
= new gifDecoder(&stream
); 
 377     if (decod
->readgif(&igif
) != E_OK
) { 
 378         wxLogDebug(_T("Error reading GIF")); 
 384     image
->Create(igif
.w
, igif
.h
); 
 391     ptr 
= image
->GetData(); 
 395     if (igif
.transparent 
!= -1) { 
 396         for (i 
= 0; i 
< 256; i
++) 
 397             if ((pal
[3 * i 
+ 0] == 255) && (pal
[3 * i 
+ 1] == 0) && (pal
[3 * i 
+ 2] == 255)) pal
[3 * i 
+ 2] = 254; 
 398         pal
[3 * (igif
.transparent
) + 0] = 255, 
 399         pal
[3 * (igif
.transparent
) + 1] = 0, 
 400         pal
[3 * (igif
.transparent
) + 2] = 255; 
 401         image
->SetMaskColour(255, 0, 255); 
 403     else image
->SetMask(FALSE
); 
 405     for (i 
= 0; i 
< igif
.w 
* igif
.h
; i
++, src
++) { 
 406         *(ptr
++) = pal
[3 * (*src
) + 0]; 
 407         *(ptr
++) = pal
[3 * (*src
) + 1]; 
 408         *(ptr
++) = pal
[3 * (*src
) + 2]; 
 416 bool wxGIFHandler::SaveFile( wxImage 
* WXUNUSED(image
), 
 417                              wxOutputStream
& WXUNUSED(stream
) ) 
 419     wxLogDebug(_T("wxGIFHandler is read-only!!"));