]>
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 We don't put pragma implement in this file because it is already present in
14 // For compilers that support precompilation, includes "wx.h".
15 #include <wx/wxprec.h>
26 #include "wx/wfstream.h"
27 #include "wx/module.h"
30 IMPLEMENT_DYNAMIC_CLASS(wxGIFHandler
,wxImageHandler
)
36 FOLLOWING CODE IS BY G.R.G. :
37 (except wxInputStream stuff)
41 /************************************************************************
42 READGIF.H - Reads a GIF file
43 ------------------------------------------------------------------------
44 Guillermo Rodriguez Garcia
48 *************************************************************************/
55 int transparent
; /* transparent color (-1 = none) */
56 unsigned char *p
; /* bitmap */
57 unsigned char *pal
; /* palette */
62 /************************************************************************
63 READGIF.C - Reads a GIF file
64 ------------------------------------------------------------------------
65 Guillermo Rodriguez Garcia
69 *************************************************************************/
77 #define E_OK 0 /* everything was OK */
78 #define E_ARCHIVO -1 /* error opening file */
79 #define E_FORMATO -2 /* error in gif header */
80 #define E_MEMORIA -3 /* error allocating memory */
83 /* This class binding is by VS, so all bugs in it are mine ;-) */
89 int restbits
; /* remaining valid bits */
90 unsigned int restbyte
; /* remaining bytes in this block */
91 unsigned int lastbyte
; /* last byte read */
93 wxInputStream
*f
; /* input file */
96 gifDecoder(wxInputStream
*s
) { f
= s
; }
97 int getcode(int bits
);
98 int dgif(IMAGEN
*img
, int interl
, int bits
);
99 int readgif(IMAGEN
*img
);
105 * Reads the next code from the file, with size 'bits'
107 int gifDecoder::getcode(int bits
)
109 unsigned int mask
; /* bit mask */
110 unsigned int code
; /* code (result) */
113 /* get remaining bits from last byte read */
114 mask
= (1 << bits
) - 1;
115 code
= (lastbyte
>> (8 - restbits
)) & mask
;
117 /* keep reading new bytes while needed */
118 while (bits
> restbits
)
120 /* if no bytes left in this block, read the next block */
122 restbyte
= (unsigned char)f
->GetC();
124 /* read next byte and isolate the bits we need */
125 lastbyte
= (unsigned char)f
->GetC();
126 mask
= (1 << (bits
- restbits
)) - 1;
127 code
= code
+ ((lastbyte
& mask
) << restbits
);
130 /* adjust total number of bits extracted from the buffer */
131 restbits
= restbits
+ 8;
134 /* find number of bits reamining for next code */
135 restbits
= (restbits
- bits
);
143 * GIF decoding function. The initial code size (aka root size)
144 * is 'bits'. Supports interlaced images (interl == 1).
146 int gifDecoder::dgif(IMAGEN
*img
, int interl
, int bits
)
148 int ab_prefix
[4096]; /* alphabet (prefixes) */
149 int ab_tail
[4096]; /* alphabet (tails) */
150 int stack
[4096]; /* decompression stack */
152 int ab_clr
; /* clear code */
153 int ab_fin
; /* end of info code */
154 int ab_bits
; /* actual symbol width, in bits */
155 int ab_free
; /* first free position in alphabet */
156 int ab_max
; /* last possible character in alphabet */
157 int pass
; /* pass number in interlaced images */
158 int pos
; /* index into decompresion stack */
159 int x
, y
; /* position in image buffer */
161 int code
, readcode
, lastcode
, abcabca
;
163 /* these won't change */
164 ab_clr
= (1 << bits
);
165 ab_fin
= (1 << bits
) + 1;
167 /* these will change through the decompression proccess */
169 ab_free
= (1 << bits
) + 2;
170 ab_max
= (1 << ab_bits
) - 1;
176 /* reset static globals */
184 readcode
= code
= getcode(ab_bits
);
187 if (code
== ab_fin
) break;
189 /* reset alphabet? */
192 /* reset main variables */
194 ab_free
= (1 << bits
) + 2;
195 ab_max
= (1 << ab_bits
) - 1;
199 /* skip to next code */
203 /* unknown code: special case (like in ABCABCA) */
206 code
= lastcode
; /* take last string */
207 stack
[pos
++] = abcabca
; /* add first character */
210 /* build the string for this code in the stack */
211 while (code
> ab_clr
)
213 stack
[pos
++] = ab_tail
[code
];
214 code
= ab_prefix
[code
];
216 stack
[pos
] = code
; /* push last code into the stack */
217 abcabca
= code
; /* save for special case */
219 /* make new entry in alphabet (only if NOT just cleared) */
222 ab_prefix
[ab_free
] = lastcode
;
223 ab_tail
[ab_free
] = code
;
226 if ((ab_free
> ab_max
) && (ab_bits
< 12))
229 ab_max
= (1 << ab_bits
) - 1;
233 /* dump stack data to the buffer */
236 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
244 /* support for interlaced images */
247 case 1: y
+= 8; break;
248 case 2: y
+= 8; break;
249 case 3: y
+= 4; break;
250 case 4: y
+= 2; break;
256 case 2: y
= 4; break;
257 case 3: y
= 2; break;
258 case 4: y
= 1; break;
273 while (code
!= ab_fin
);
281 * Reads a GIF image from the file with filename 'nombre' in the
282 * IMAGEN structure pointed by 'img'. Can read GIFs with any bit
283 * size (color depth), but the output image is always expanded
284 * to 8 bits per pixel. Also, the image palette always contains
285 * 256 colors, although some of them may be unused. Returns E_OK
286 * (== 0) on success, or an error code if something fails. Error
287 * codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see above).
289 int gifDecoder::readgif(IMAGEN
*img
)
291 int size
, ncolors
, bits
, interl
, i
;
292 unsigned char pal
[768];
293 unsigned char buf
[16];
296 /* read header and logical screen descriptor block (LSDB) */
299 /* check GIF signature */
300 if (memcmp(buf
, "GIF", 3) != 0) return E_FORMATO
;
302 /* load global color map if available */
303 if ((buf
[10] & 0x80) == 0x80)
305 ncolors
= 2 << (buf
[10] & 0x07);
306 f
->Read(pal
, 3 * ncolors
);
309 /* assume no transparent color */
310 img
->transparent
= -1;
312 /* skip most extensions */
313 while (((unsigned char)f
->GetC()) == 0x21) /* separator */
315 if (((unsigned char)f
->GetC()) == 0xF9) /* graphic control ext. */
319 img
->transparent
= buf
[4];
322 while ((i
= (unsigned char)f
->GetC()) != 0) /* byte count */
323 f
->SeekI(i
, wxFromCurrent
);
326 /* read image descriptor block (IDB) */
328 img
->w
= buf
[4] + 256 * buf
[5];
329 img
->h
= buf
[6] + 256 * buf
[7];
330 size
= img
->w
* img
->h
;
331 interl
= ((buf
[8] & 0x40)? 1 : 0);
333 /* load local color map if available */
334 if ((buf
[8] & 0x80) == 0x80)
336 ncolors
= 2 << (buf
[8] & 0x07);
337 f
->Read(pal
, 3 * ncolors
);
340 /* get initial code size from first byte in raster data */
341 bits
= (unsigned char)f
->GetC();
343 /* allocate memory for image and palette */
344 if ((img
->p
= (unsigned char*) malloc(size
)) == NULL
) return E_MEMORIA
;
345 if ((img
->pal
= (unsigned char*) malloc(768)) == NULL
) return E_MEMORIA
;
347 /* shift palette to fit VGA 6-bit format */
348 for (i
= 0; i
< 768; i
++)
349 (img
->pal
)[i
] = (unsigned char)pal
[i
]; /* >> 2 not in wxWin */
352 dgif(img
, interl
, bits
);
354 /* finish successfully :-) */
362 FOLLOWING CODE IS BY V.S. :
366 //-----------------------------------------------------------------------------
368 //-----------------------------------------------------------------------------
370 bool wxGIFHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
372 unsigned char *ptr
, *src
, *pal
;
379 decod
= new gifDecoder(&stream
);
381 if (decod
->readgif(&igif
) != E_OK
) {
382 wxLogDebug(_T("Error reading GIF"));
388 image
->Create(igif
.w
, igif
.h
);
395 ptr
= image
->GetData();
399 if (igif
.transparent
!= -1) {
400 for (i
= 0; i
< 256; i
++)
401 if ((pal
[3 * i
+ 0] == 255) && (pal
[3 * i
+ 1] == 0) && (pal
[3 * i
+ 2] == 255)) pal
[3 * i
+ 2] = 254;
402 pal
[3 * (igif
.transparent
) + 0] = 255,
403 pal
[3 * (igif
.transparent
) + 1] = 0,
404 pal
[3 * (igif
.transparent
) + 2] = 255;
405 image
->SetMaskColour(255, 0, 255);
407 else image
->SetMask(FALSE
);
409 for (i
= 0; i
< igif
.w
* igif
.h
; i
++, src
++) {
410 *(ptr
++) = pal
[3 * (*src
) + 0];
411 *(ptr
++) = pal
[3 * (*src
) + 1];
412 *(ptr
++) = pal
[3 * (*src
) + 2];
420 bool wxGIFHandler::SaveFile( wxImage
* WXUNUSED(image
),
421 wxOutputStream
& WXUNUSED(stream
) )
423 wxLogDebug(_T("wxGIFHandler is read-only!!"));