]>
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 unsigned char *p
; /* bitmap */
51 unsigned char *pal
; /* palette */
55 /************************************************************************
56 READGIF.C - Lee un archivo GIF de 256 colores
57 ------------------------------------------------------------------------
58 Tratamiento Digital de la Imagen
59 ------------------------------------------------------------------------
60 Guillermo Rodriguez Garcia
64 *************************************************************************/
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 unsigned char* file
; /* input file in memory */
90 unsigned int file_pos
, file_size
; /* position & size in it */
93 void fread(void *ptr
, size_t size
, size_t nmemb
);
94 void fseekcur(int rel_pos
);
97 gifDecoder(unsigned char* mem
, int sz
) {file
= mem
; file_pos
= 0; file_size
= sz
;}
98 int getcode(int bits
);
99 int dgif(IMAGEN
*img
, int interl
, int bits
);
100 int readgif(IMAGEN
*img
);
104 int gifDecoder::fgetc()
106 if (file_pos
< file_size
) return file
[file_pos
++];
110 void gifDecoder::fread(void *ptr
, size_t size
, size_t nmemb
)
112 int todo
= size
* nmemb
;
113 if (todo
+ file_pos
> file_size
) todo
= file_size
- file_pos
;
114 memcpy(ptr
, file
+ file_pos
, todo
);
118 void gifDecoder::fseekcur(int rel_pos
)
124 * Reads the next code from the file, with size 'bits'
125 * v2.0 - changed to support 'bits' values < 8
127 int gifDecoder::getcode(int bits
)
129 unsigned int mask
; /* bit mask */
130 unsigned int code
; /* code (result) */
133 /* get remaining bits from last byte read */
134 mask
= (1 << bits
) - 1;
135 code
= (lastbyte
>> (8 - restbits
)) & mask
;
137 /* keep reading new bytes until needed */
138 while (bits
> restbits
)
140 /* if no bytes left in this block, read the next block */
144 /* read next byte and isolate the bits we need */
146 mask
= (1 << (bits
- restbits
)) - 1;
147 code
= code
+ ((lastbyte
& mask
) << restbits
);
150 /* adjust total number of bits extracted from the buffer */
151 restbits
= restbits
+ 8;
154 /* find number of bits reamining for next code */
155 restbits
= (restbits
- bits
);
161 * GIF decoding function. The initial code size (aka root size)
162 * is 'bits'. Supports interlaced images (interl == 1).
164 int gifDecoder::dgif(IMAGEN
*img
, int interl
, int bits
)
166 int ab_prefix
[4096]; /* alphabet (prefixes) */
167 int ab_tail
[4096]; /* alphabet (tails) */
168 int stack
[4096]; /* decompression stack */
170 int ab_clr
; /* clear code */
171 int ab_fin
; /* end of info code */
172 int ab_bits
; /* actual symbol width, in bits */
173 int ab_free
; /* first free position in alphabet */
174 int ab_max
; /* last possible character in alphabet */
175 int pass
; /* pass number in interlaced images */
176 int pos
; /* index into decompresion stack */
177 int x
, y
; /* position in image buffer */
179 int code
, readcode
, lastcode
, abcabca
;
181 /* these won't change */
182 ab_clr
= (1 << bits
);
183 ab_fin
= (1 << bits
) + 1;
185 /* these will change through the decompression proccess */
187 ab_free
= (1 << bits
) + 2;
188 ab_max
= (1 << ab_bits
) - 1;
194 /* reset static globals */
202 readcode
= code
= getcode(ab_bits
);
205 if (code
== ab_fin
) break;
207 /* reset alphabet? */
210 /* reset main variables */
212 ab_free
= (1 << bits
) + 2;
213 ab_max
= (1 << ab_bits
) - 1;
217 /* skip to next code */
221 /* unknown code: special case (like in ABCABCA) */
224 code
= lastcode
; /* take last string */
225 stack
[pos
++] = abcabca
; /* add first character */
228 /* build the string for this code in the stack */
229 while (code
> ab_clr
)
231 stack
[pos
++] = ab_tail
[code
];
232 code
= ab_prefix
[code
];
234 stack
[pos
] = code
; /* push last code into the stack */
235 abcabca
= code
; /* save for special case */
237 /* make new entry in alphabet (only if NOT just cleared) */
240 ab_prefix
[ab_free
] = lastcode
;
241 ab_tail
[ab_free
] = code
;
244 if ((ab_free
> ab_max
) && (ab_bits
< 12))
247 ab_max
= (1 << ab_bits
) - 1;
251 /* dump stack data to the buffer */
254 (img
->p
)[x
+ (y
* (img
->w
))] = (char)stack
[pos
--];
262 /* support for interlaced images */
265 case 1: y
+= 8; break;
266 case 2: y
+= 8; break;
267 case 3: y
+= 4; break;
268 case 4: y
+= 2; break;
274 case 2: y
= 4; break;
275 case 3: y
= 2; break;
276 case 4: y
= 1; break;
291 while (code
!= ab_fin
);
297 * Reads a GIF image from the file with filename 'nombre' in the
298 * IMAGEN structure pointed by 'img'. Can read GIFs with any bit
299 * size (color depth), but the output image is always expanded
300 * to 8 bits per pixel. Also, the image palette always contains
301 * 256 colors, although some of them may be unused. Returns E_OK
302 * (== 0) on success, or an error code if something fails. Error
303 * codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see above).
305 int gifDecoder::readgif(IMAGEN
*img
)
307 int size
, ncolors
, bits
, interl
, i
;
308 unsigned char pal
[768];
309 unsigned char buf
[16];
312 /* read header and logical screen descriptor block (LSDB) */
315 /* check GIF signature */
316 if (memcmp(buf
, "GIF", 3) != 0) return E_FORMATO
;
318 /* load global color map if available */
319 if ((buf
[10] & 0x80) == 0x80)
321 ncolors
= 2 << (buf
[10] & 0x07);
322 fread(pal
, 1, 3 * ncolors
);
325 /* skip extensions */
326 while (fgetc() == 0x21) /* separator */
328 fgetc(); /* function code */
330 while ((i
= fgetc()) != 0) /* byte count */
334 /* read image descriptor block (IDB) */
336 img
->w
= buf
[4] + 256 * buf
[5];
338 img
->h
= buf
[6] + 256 * buf
[7];
339 size
= img
->w
* img
->h
;
340 interl
= ((buf
[8] & 0x40)? 1 : 0);
342 /* load local color map if available */
343 if ((buf
[8] & 0x80) == 0x80)
345 ncolors
= 2 << (buf
[8] & 0x07);
346 fread(pal
, 1, 3 * ncolors
);
349 /* get initial code size from first byte in raster data */
352 /* allocate memory for image and palette */
353 if ((img
->p
= (unsigned char*) malloc(size
)) == NULL
) return E_MEMORIA
;
354 if ((img
->pal
= (unsigned char*) malloc(768)) == NULL
) return E_MEMORIA
;
356 /* shift palette to fit VGA 6-bit format */
357 for (i
= 0; i
< 768; i
++)
358 (img
->pal
)[i
] = (unsigned char)pal
[i
] /* >> 2 not needed under wxWin */;
361 dgif(img
, interl
, bits
);
363 /* finish successfully :-) */
369 FOLLOWING CODE IS BY V.S. :
373 //-----------------------------------------------------------------------------
375 //-----------------------------------------------------------------------------
377 IMPLEMENT_DYNAMIC_CLASS(wxGIFHandler
,wxImageHandler
)
379 bool wxGIFHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
381 unsigned char *ptr
, *src
, *pal
;
383 unsigned char* file_con
;
390 file_size
= stream
.StreamSize();
391 file_con
= (unsigned char*) malloc(file_size
);
392 stream
.Read(file_con
, file_size
);
393 decod
= new gifDecoder(file_con
, file_size
);
395 if (decod
-> readgif(&igif
) != E_OK
) {
396 wxLogDebug("Error reading GIF");
404 image
->Create(igif
.w
, igif
.h
);
410 image
->SetMask(FALSE
);
412 ptr
= image
->GetData();
415 for (i
= 0; i
< igif
.w
* igif
.h
; i
++, src
++) {
416 *(ptr
++) = pal
[3 * (*src
) + 0];
417 *(ptr
++) = pal
[3 * (*src
) + 1];
418 *(ptr
++) = pal
[3 * (*src
) + 2];
426 bool wxGIFHandler::SaveFile( wxImage
*image
, wxOutputStream
& stream
)
428 wxLogDebug("wxGIFHandler is read-only!!");
432 //////////////////// Module:
434 /* We haven't yet decided to go for the wxModule approach or
435 * explicit handler-adding: assuming the latter for now -- JACS
437 class wxGIFModule : public wxModule
439 DECLARE_DYNAMIC_CLASS(wxGIFModule)
442 virtual bool OnInit()
444 wxImage::AddHandler(new wxGIFHandler);
447 virtual void OnExit() {}
450 IMPLEMENT_DYNAMIC_CLASS(wxGIFModule, wxModule)