35 #if GIFLIB_MAJOR > 5 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
36 #define DGifCloseFile(gif) DGifCloseFile(gif, NULL)
37 #define EGifCloseFile(gif) EGifCloseFile(gif, NULL)
38 #define DGifOpenFileName(gif) DGifOpenFileName(gif, NULL)
39 #define EGifOpenFileName(gif, exist) EGifOpenFileName(gif, exist, NULL)
41 #define QuantizeBuffer GifQuantizeBuffer
42 #define MakeMapObject GifMakeMapObject
43 #define FreeMapObject GifFreeMapObject
65 strncpy(buffer,
"GIF loader: Error opening file", buflen);
68 strncpy(buffer,
"GIF loader: Error reading file", buflen);
71 strncpy(buffer,
"GIF loader: Error writing file", buflen);
74 strncpy(buffer,
"GIF loader: Out of memory error", buflen);
82 const unsigned char *header,
85 return (headerlen >= 3)
92 decode_row(GifFileType * giffile,
93 unsigned char * buffer,
94 unsigned char * rowdata,
95 int x,
int y,
int len,
98 GifColorType * cmentry;
99 ColorMapObject * colormap;
104 y = giffile->SHeight - (y+1);
105 ptr = buffer + (giffile->SWidth * y + x) * 4;
107 colormap = (giffile->Image.ColorMap
108 ? giffile->Image.ColorMap
109 : giffile->SColorMap);
110 colormapsize = colormap ? colormap->ColorCount : 255;
114 if (col >= colormapsize) col = 0;
115 cmentry = colormap ? &colormap->Colors[col] : NULL;
117 *ptr++ = cmentry->Red;
118 *ptr++ = cmentry->Green;
119 *ptr++ = cmentry->Blue;
126 *ptr++ = (col == transparent ? 0x00 : 0xff);
134 int *numComponents_ret)
136 int i, j, n, row, col, width, height, extcode;
137 unsigned char * rowdata;
138 unsigned char * buffer, * ptr;
141 GifRecordType recordtype;
142 GifByteType * extension;
143 GifFileType * giffile;
144 GifColorType * bgcol;
147 int interlacedoffset[] = { 0, 4, 2, 1 };
148 int interlacedjumps[] = { 8, 8, 4, 2 };
150 giffile = DGifOpenFileName(filename);
158 n = giffile->SHeight * giffile->SWidth;
159 buffer = (
unsigned char*) malloc(n * 4);
164 rowdata = (
unsigned char*) malloc(giffile->SWidth);
171 bg = giffile->SBackGroundColor;
172 if (giffile->SColorMap && bg < giffile->SColorMap->ColorCount) {
173 bgcol = &giffile->SColorMap->Colors[bg];
177 for (i = 0; i < n; i++) {
180 *ptr++ = bgcol->Green;
181 *ptr++ = bgcol->Blue;
194 if (DGifGetRecordType(giffile, &recordtype) == GIF_ERROR) {
200 switch (recordtype) {
201 case IMAGE_DESC_RECORD_TYPE:
202 if (DGifGetImageDesc(giffile) == GIF_ERROR) {
208 row = giffile->Image.Top;
209 col = giffile->Image.Left;
210 width = giffile->Image.Width;
211 height = giffile->Image.Height;
212 if (giffile->Image.Left + giffile->Image.Width > giffile->SWidth ||
213 giffile->Image.Top + giffile->Image.Height > giffile->SHeight) {
220 if (giffile->Image.Interlace) {
222 for (i = 0; i < 4; i++) {
223 for (j = row + interlacedoffset[i]; j < row + height;
224 j += interlacedjumps[i]) {
225 if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) {
231 else decode_row(giffile, buffer, rowdata, col, j, width, transparent);
236 for (i = 0; i < height; i++, row++) {
237 if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) {
243 else decode_row(giffile, buffer, rowdata, col, row, width, transparent);
247 case EXTENSION_RECORD_TYPE:
249 if (DGifGetExtension(giffile, &extcode, &extension) == GIF_ERROR) {
256 else if (extcode == 0xf9) {
257 if (extension[0] >= 4 && extension[1] & 0x1) transparent = extension[4];
258 else transparent = -1;
260 while (extension != NULL) {
261 if (DGifGetExtensionNext(giffile, &extension) == GIF_ERROR) {
269 case TERMINATE_RECORD_TYPE:
275 while (recordtype != TERMINATE_RECORD_TYPE);
278 *width_ret = giffile->SWidth;
279 *height_ret = giffile->SHeight;
280 *numComponents_ret = 4;
281 DGifCloseFile(giffile);
287 const unsigned char * bytes,
292 const unsigned char * bytes_ptr = bytes;
293 int i, colormapsize = 256;
294 int bufsize = width * height;
295 ColorMapObject * cmapobj;
296 GifByteType * outbuf = NULL, * outbuf_ptr = NULL;
297 GifByteType * rgbbuf = NULL, * rgbbuf_ptr = NULL;
298 GifFileType * giffile = NULL;
301 if (!(rgbbuf = (GifByteType*)malloc(bufsize*3))) {
310 switch (numcomponents) {
314 for (i=0; i < bufsize; i++) {
315 rgbbuf_ptr[0] = *bytes_ptr++;
316 rgbbuf_ptr[bufsize] = *bytes_ptr++;
317 rgbbuf_ptr[bufsize*2] = *bytes_ptr++;
319 if (numcomponents == 4) { bytes_ptr++; }
326 for (i=0; i < bufsize; i++) {
327 rgbbuf_ptr[0] = rgbbuf_ptr[bufsize] = rgbbuf_ptr[bufsize*2] = *bytes_ptr++;
329 if (numcomponents == 2) { bytes_ptr++; }
339 if (!(outbuf = (GifByteType*)malloc(bufsize))) {
345 if (!(cmapobj = MakeMapObject(colormapsize, NULL))) {
352 if (QuantizeBuffer(width, height, &colormapsize,
353 rgbbuf, &rgbbuf[bufsize], &rgbbuf[bufsize*2],
354 outbuf, cmapobj->Colors) == GIF_ERROR) {
358 FreeMapObject(cmapobj);
363 if (!(giffile = EGifOpenFileName(filename, FALSE))) {
367 FreeMapObject(cmapobj);
371 if (EGifPutScreenDesc(giffile, width, height, 8,
372 0, cmapobj) == GIF_ERROR ||
373 EGifPutImageDesc(giffile, 0, 0, width, height,
374 FALSE, NULL) == GIF_ERROR) {
378 EGifCloseFile(giffile);
379 FreeMapObject(cmapobj);
383 outbuf_ptr = outbuf + bufsize;
384 for (i = height; i > 0; i--) {
386 if (EGifPutLine(giffile, outbuf_ptr, width) == GIF_ERROR) {
390 EGifCloseFile(giffile);
391 FreeMapObject(cmapobj);
396 if (EGifPutComment(giffile,
"Image saved using simage.") == GIF_ERROR ||
397 EGifCloseFile(giffile) == GIF_ERROR) {
401 EGifCloseFile(giffile);
402 FreeMapObject(cmapobj);
408 FreeMapObject(cmapobj);
int simage_gif_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
int simage_gif_identify(const char *filename, const unsigned char *header, int headerlen)
int simage_gif_error(char *buffer, int bufferlen)
unsigned char * simage_gif_load(const char *filename, int *width, int *height, int *numComponents)