]>
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 - Leer un archivo GIF de 8 bits
37 ------------------------------------------------------------------------
38 Tratamiento Digital de la Imagen
39 ------------------------------------------------------------------------
40 Guillermo Rodriguez Garcia
44 *************************************************************************/
50 int transparent
; /* transparent color (-1 = none) */
51 unsigned char *p
; /* bitmap */
52 unsigned char *pal
; /* palette */
56 /************************************************************************
57 READGIF.C - Lee un archivo GIF de 256 colores
58 ------------------------------------------------------------------------
59 Tratamiento Digital de la Imagen
60 ------------------------------------------------------------------------
61 Guillermo Rodriguez Garcia
65 *************************************************************************/
73 #define E_OK 0 /* everything was OK */
74 #define E_ARCHIVO -1 /* error opening file */
75 #define E_FORMATO -2 /* error in gif header */
76 #define E_MEMORIA -3 /* error allocating memory */
79 /* This class binding is by VS, so all bugs in it are mine ;-) */
85 int restbits
; /* remaining valid bits */
86 unsigned int restbyte
; /* remaining bytes in this block */
87 unsigned int lastbyte
; /* last byte read */
89 wxInputStream
*f
; /* input file */
92 gifDecoder(wxInputStream
*s
) {f
= s
;}
93 int getcode(int bits
);
94 int dgif(IMAGEN
*img
, int interl
, int bits
);
95 int readgif(IMAGEN
*img
);
98 unsigned char mygetc();
99 // This is NEEDED! GetC is char (signed) why we need unsigned value
104 unsigned char gifDecoder::mygetc()
113 * Reads the next code from the file, with size 'bits'
114 * v2.0 - changed to support 'bits' values < 8
116 int gifDecoder::getcode(int bits
)
118 unsigned int mask
; /* bit mask */
119 unsigned int code
; /* code (result) */
122 /* get remaining bits from last byte read */
123 mask
= (1 << bits
) - 1;
124 code
= (lastbyte
>> (8 - restbits
)) & mask
;
126 /* keep reading new bytes until needed */
127 while (bits
> restbits
)
129 /* if no bytes left in this block, read the next block */
133 /* read next byte and isolate the bits we need */
135 mask
= (1 << (bits
- restbits
)) - 1;
136 code
= code
+ ((lastbyte
& mask
) << restbits
);
139 /* adjust total number of bits extracted from the buffer */
140 restbits
= restbits
+ 8;
143 /* find number of bits reamining for next code */
144 restbits
= (restbits
- bits
);
151 * GIF decoding function. The initial code size (aka root size)
152 * is 'bits'. Supports interlaced images (interl == 1).
154 int gifDecoder::dgif(IMAGEN
*img
, int interl
, int bits
)
156 int ab_prefix
[4096]; /* alphabet (prefixes) */
157 int ab_tail
[4096]; /* alphabet (tails) */
158 int stack
[4096]; /* decompression stack */
160 int ab_clr
; /* clear code */
161 int ab_fin
; /* end of info code */
162 int ab_bits
; /* actual symbol width, in bits */
163 int ab_free
; /* first free position in alphabet */
164 int ab_max
; /* last possible character in alphabet */
165 int pass
; /* pass number in interlaced images */
166 int pos
; /* index into decompresion stack */
167 int x
, y
; /* position in image buffer */
169 int code
, readcode
, lastcode
, abcabca
;
171 /* these won't change */
172 ab_clr
= (1 << bits
);
173 ab_fin
= (1 << bits
) + 1;
175 /* these will change through the decompression proccess */
177 ab_free
= (1 << bits
) + 2;
178 ab_max
= (1 << ab_bits
) - 1;
184 /* reset static globals */
192 readcode
= code
= getcode(ab_bits
);
195 if (code
== ab_fin
) break;
197 /* reset alphabet? */
200 /* reset main variables */
202 ab_free
= (1 << bits
) + 2;
203 ab_max
= (1 << ab_bits
) - 1;
207 /* skip to next code */
211 /* unknown code: special case (like in ABCABCA) */
214 code
= lastcode
; /* take last string */
215 stack
[pos
++] = abcabca
; /* add first character */
218 /* build the string for this code in the stack */
219 while (code
> ab_clr
)
221 stack
[pos
++] = ab_tail
[code
];
222 code
= ab_prefix
[code
];
224 stack
[pos
] = code
; /* push last code into the stack */
225 abcabca
= code
; /* save for special case */
227 /* make new entry in alphabet (only if NOT just cleared) */
230 ab_prefix
[ab_free
] = lastcode
;
231 ab_tail
[ab_free
] = code
;
234 if ((ab_free
> ab_max
) && (ab_bits
< 12))
237 ab_max
= (1 << ab_bits
) - 1;
241 /* dump stack data to the buffer */
244 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
252 /* support for interlaced images */
255 case 1: y
+= 8; break;
256 case 2: y
+= 8; break;
257 case 3: y
+= 4; break;
258 case 4: y
+= 2; break;
264 case 2: y
= 4; break;
265 case 3: y
= 2; break;
266 case 4: y
= 1; break;
281 while (code
!= ab_fin
);
287 * Reads a GIF image from the file with filename 'nombre' in the
288 * IMAGEN structure pointed by 'img'. Can read GIFs with any bit
289 * size (color depth), but the output image is always expanded
290 * to 8 bits per pixel. Also, the image palette always contains
291 * 256 colors, although some of them may be unused. Returns E_OK
292 * (== 0) on success, or an error code if something fails. Error
293 * codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see above).
295 int gifDecoder::readgif(IMAGEN
*img
)
297 int size
, ncolors
, bits
, interl
, i
;
298 unsigned char pal
[768];
299 unsigned char buf
[16];
301 /* read header and logical screen descriptor block (LSDB) */
304 /* check GIF signature */
305 if (memcmp(buf
, "GIF", 3) != 0) return E_FORMATO
;
307 /* load global color map if available */
308 if ((buf
[10] & 0x80) == 0x80)
310 ncolors
= 2 << (buf
[10] & 0x07);
311 f
-> Read(pal
, 3 * ncolors
);
314 /* assume no transparent color */
315 img
->transparent
= -1;
317 /* skip most extensions */
318 while (mygetc() == 0x21) /* separator */
321 if (mygetc() == 0xF9) /* graphic control ext. */
325 wxLogDebug("buf[1] is %i (%i)", buf
[1], buf
[1] & 0x01);
327 wxLogDebug("setting transparen %i", buf
[4]);
328 img
->transparent
= buf
[4];
332 while ((i
= mygetc()) != 0) /* byte count */
333 f
->SeekI(i
, wxFromCurrent
);
336 /* read image descriptor block (IDB) */
338 img
->w
= buf
[4] + 256 * buf
[5];
340 img
->h
= buf
[6] + 256 * buf
[7];
341 size
= img
->w
* img
->h
;
342 interl
= ((buf
[8] & 0x40)? 1 : 0);
344 /* load local color map if available */
345 if ((buf
[8] & 0x80) == 0x80)
347 ncolors
= 2 << (buf
[8] & 0x07);
348 f
-> Read(pal
, 3 * ncolors
);
351 /* get initial code size from first byte in raster data */
354 /* allocate memory for image and palette */
355 if ((img
->p
= (unsigned char*) malloc(size
)) == NULL
) return E_MEMORIA
;
356 if ((img
->pal
= (unsigned char*) malloc(768)) == NULL
) return E_MEMORIA
;
358 /* shift palette to fit VGA 6-bit format */
359 for (i
= 0; i
< 768; i
++)
360 (img
->pal
)[i
] = (unsigned char)pal
[i
] /* >> 2 not needed under wxWin */;
363 dgif(img
, interl
, bits
);
365 /* finish successfully :-) */
371 FOLLOWING CODE IS BY V.S. :
375 //-----------------------------------------------------------------------------
377 //-----------------------------------------------------------------------------
379 IMPLEMENT_DYNAMIC_CLASS(wxGIFHandler
,wxImageHandler
)
381 bool wxGIFHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
383 unsigned char *ptr
, *src
, *pal
;
390 decod
= new gifDecoder(&stream
);
392 if (decod
-> readgif(&igif
) != E_OK
) {
393 wxLogDebug(_T("Error reading GIF"));
399 image
->Create(igif
.w
, igif
.h
);
405 image
->SetMask(FALSE
);
407 ptr
= image
->GetData();
410 for (i
= 0; i
< igif
.w
* igif
.h
; i
++, src
++) {
411 *(ptr
++) = pal
[3 * (*src
) + 0];
412 *(ptr
++) = pal
[3 * (*src
) + 1];
413 *(ptr
++) = pal
[3 * (*src
) + 2];
416 if (igif
.transparent
!= -1) {
418 image
->SetMaskColour(pal
[3 * (igif
.transparent
) + 0], pal
[3 * (igif
.transparent
) + 0], pal
[3 * (igif
.transparent
) + 0]);
419 image
->SetMask(TRUE
);
422 wxLogDebug("(unsigned int)%i", (unsigned int)-1);
428 bool wxGIFHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
430 wxLogDebug(_T("wxGIFHandler is read-only!!"));