34 #if GIFLIB_MAJOR > 5 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 2 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE >= 9
40 #if GIFLIB_MAJOR > 5 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
41 #define DGifCloseFile(gif) DGifCloseFile(gif, NULL)
42 #define EGifCloseFile(gif) EGifCloseFile(gif, NULL)
43 #define DGifOpenFileName(gif) DGifOpenFileName(gif, NULL)
44 #define EGifOpenFileName(gif, exist) EGifOpenFileName(gif, exist, NULL)
46 #define QuantizeBuffer GifQuantizeBuffer
47 #define MakeMapObject GifMakeMapObject
48 #define FreeMapObject GifFreeMapObject
70 strncpy(buffer,
"GIF loader: Error opening file", buflen);
73 strncpy(buffer,
"GIF loader: Error reading file", buflen);
76 strncpy(buffer,
"GIF loader: Error writing file", buflen);
79 strncpy(buffer,
"GIF loader: Out of memory error", buflen);
87 const unsigned char *header,
90 return (headerlen >= 3)
97 decode_row(GifFileType * giffile,
98 unsigned char * buffer,
99 unsigned char * rowdata,
100 int x,
int y,
int len,
103 GifColorType * cmentry;
104 ColorMapObject * colormap;
109 y = giffile->SHeight - (y+1);
110 ptr = buffer + (giffile->SWidth * y + x) * 4;
112 colormap = (giffile->Image.ColorMap
113 ? giffile->Image.ColorMap
114 : giffile->SColorMap);
115 colormapsize = colormap ? colormap->ColorCount : 255;
119 if (col >= colormapsize) col = 0;
120 cmentry = colormap ? &colormap->Colors[col] : NULL;
122 *ptr++ = cmentry->Red;
123 *ptr++ = cmentry->Green;
124 *ptr++ = cmentry->Blue;
131 *ptr++ = (col == transparent ? 0x00 : 0xff);
139 int *numComponents_ret)
141 int i, j, n, row, col, width, height, extcode;
142 unsigned char * rowdata;
143 unsigned char * buffer, * ptr;
146 GifRecordType recordtype;
147 GifByteType * extension;
148 GifFileType * giffile;
149 GifColorType * bgcol;
152 int interlacedoffset[] = { 0, 4, 2, 1 };
153 int interlacedjumps[] = { 8, 8, 4, 2 };
155 giffile = DGifOpenFileName(filename);
163 n = giffile->SHeight * giffile->SWidth;
164 buffer = (
unsigned char*) malloc(n * 4);
169 rowdata = (
unsigned char*) malloc(giffile->SWidth);
176 bg = giffile->SBackGroundColor;
177 if (giffile->SColorMap && bg < giffile->SColorMap->ColorCount) {
178 bgcol = &giffile->SColorMap->Colors[bg];
182 for (i = 0; i < n; i++) {
185 *ptr++ = bgcol->Green;
186 *ptr++ = bgcol->Blue;
199 if (DGifGetRecordType(giffile, &recordtype) == GIF_ERROR) {
205 switch (recordtype) {
206 case IMAGE_DESC_RECORD_TYPE:
207 if (DGifGetImageDesc(giffile) == GIF_ERROR) {
213 row = giffile->Image.Top;
214 col = giffile->Image.Left;
215 width = giffile->Image.Width;
216 height = giffile->Image.Height;
217 if (giffile->Image.Left + giffile->Image.Width > giffile->SWidth ||
218 giffile->Image.Top + giffile->Image.Height > giffile->SHeight) {
225 if (giffile->Image.Interlace) {
227 for (i = 0; i < 4; i++) {
228 for (j = row + interlacedoffset[i]; j < row + height;
229 j += interlacedjumps[i]) {
230 if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) {
236 else decode_row(giffile, buffer, rowdata, col, j, width, transparent);
241 for (i = 0; i < height; i++, row++) {
242 if (DGifGetLine(giffile, rowdata, width) == GIF_ERROR) {
248 else decode_row(giffile, buffer, rowdata, col, row, width, transparent);
252 case EXTENSION_RECORD_TYPE:
254 if (DGifGetExtension(giffile, &extcode, &extension) == GIF_ERROR) {
261 else if (extcode == 0xf9) {
262 if (extension[0] >= 4 && extension[1] & 0x1) transparent = extension[4];
263 else transparent = -1;
265 while (extension != NULL) {
266 if (DGifGetExtensionNext(giffile, &extension) == GIF_ERROR) {
274 case TERMINATE_RECORD_TYPE:
280 while (recordtype != TERMINATE_RECORD_TYPE);
283 *width_ret = giffile->SWidth;
284 *height_ret = giffile->SHeight;
285 *numComponents_ret = 4;
286 DGifCloseFile(giffile);
292 const unsigned char * bytes,
297 const unsigned char * bytes_ptr = bytes;
298 int i, colormapsize = 256;
299 int bufsize = width * height;
300 ColorMapObject * cmapobj;
301 GifByteType * outbuf = NULL, * outbuf_ptr = NULL;
302 GifByteType * rgbbuf = NULL, * rgbbuf_ptr = NULL;
303 GifFileType * giffile = NULL;
306 if (!(rgbbuf = (GifByteType*)malloc(bufsize*3))) {
315 switch (numcomponents) {
319 for (i=0; i < bufsize; i++) {
320 rgbbuf_ptr[0] = *bytes_ptr++;
321 rgbbuf_ptr[bufsize] = *bytes_ptr++;
322 rgbbuf_ptr[bufsize*2] = *bytes_ptr++;
324 if (numcomponents == 4) { bytes_ptr++; }
331 for (i=0; i < bufsize; i++) {
332 rgbbuf_ptr[0] = rgbbuf_ptr[bufsize] = rgbbuf_ptr[bufsize*2] = *bytes_ptr++;
334 if (numcomponents == 2) { bytes_ptr++; }
344 if (!(outbuf = (GifByteType*)malloc(bufsize))) {
350 if (!(cmapobj = MakeMapObject(colormapsize, NULL))) {
357 if (QuantizeBuffer(width, height, &colormapsize,
358 rgbbuf, &rgbbuf[bufsize], &rgbbuf[bufsize*2],
359 outbuf, cmapobj->Colors) == GIF_ERROR) {
363 FreeMapObject(cmapobj);
368 if (!(giffile = EGifOpenFileName(filename, FALSE))) {
372 FreeMapObject(cmapobj);
376 if (EGifPutScreenDesc(giffile, width, height, 8,
377 0, cmapobj) == GIF_ERROR ||
378 EGifPutImageDesc(giffile, 0, 0, width, height,
379 FALSE, NULL) == GIF_ERROR) {
383 EGifCloseFile(giffile);
384 FreeMapObject(cmapobj);
388 outbuf_ptr = outbuf + bufsize;
389 for (i = height; i > 0; i--) {
391 if (EGifPutLine(giffile, outbuf_ptr, width) == GIF_ERROR) {
395 EGifCloseFile(giffile);
396 FreeMapObject(cmapobj);
401 if (EGifPutComment(giffile,
"Image saved using simage.") == GIF_ERROR ||
402 EGifCloseFile(giffile) == GIF_ERROR) {
406 EGifCloseFile(giffile);
407 FreeMapObject(cmapobj);
413 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)