]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imaggif.cpp
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!!"));