=cut
*/
+static char const *gif_error_msg(int code);
+static void gif_push_error();
+
#if IM_GIFMAJOR >= 4
/*
for (i = 0; i < 4; ++i) {
for (j = InterlacedOffset[i]; j < img->ysize; j += InterlacedJumps[i]) {
if (EGifPutLine(gf, data+j*img->xsize, img->xsize) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image data:");
mm_log((1, "Error in EGifPutLine\n"));
EGifCloseFile(gf);
return 0;
int y;
for (y = 0; y < img->ysize; ++y) {
if (EGifPutLine(gf, data, img->xsize) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image data:");
mm_log((1, "Error in EGifPutLine\n"));
EGifCloseFile(gf);
return 0;
++want_gce;
}
if (want_gce) {
- return EGifPutExtension(gf, 0xF9, sizeof(gce), gce) != GIF_ERROR;
+ if (EGifPutExtension(gf, 0xF9, sizeof(gce), gce) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save GCE");
+ }
}
return 1;
}
int i;
int size = quant->mc_count;
int map_size;
+ ColorMapObject *map;
for (i = 0; i < quant->mc_count; ++i) {
colors[i].Red = quant->mc_colors[i].rgb.r;
/* giflib spews for 1 colour maps, reasonable, I suppose */
if (map_size == 1)
map_size = 2;
- return MakeMapObject(map_size, colors);
+ map = MakeMapObject(map_size, colors);
+ if (!map) {
+ gif_push_error();
+ i_push_error(0, "Could not create color map object");
+ return NULL;
+ }
+ return map;
}
/*
}
}
-
- if (count <= 0)
+ if (count <= 0) {
+ i_push_error(0, "No images provided to write");
return 0; /* what are you smoking? */
+ }
orig_count = quant->mc_count;
orig_size = quant->mc_size;
++color_bits;
if (EGifPutScreenDesc(gf, scrw, scrh, color_bits, 0, map) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save screen descriptor");
FreeMapObject(map);
myfree(result);
EGifCloseFile(gf);
posx = posy = 0;
if (EGifPutImageDesc(gf, posx, posy, imgs[0]->xsize, imgs[0]->ysize,
opts->interlace, NULL) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image descriptor");
EGifCloseFile(gf);
mm_log((1, "Error in EGifPutImageDesc."));
return 0;
if (EGifPutImageDesc(gf, posx, posy, imgs[imgn]->xsize,
imgs[imgn]->ysize, opts->interlace,
map) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image descriptor");
myfree(result);
FreeMapObject(map);
EGifCloseFile(gf);
++color_bits;
if (EGifPutScreenDesc(gf, scrw, scrh, color_bits, 0, map) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save screen descriptor");
FreeMapObject(map);
myfree(result);
EGifCloseFile(gf);
posx = posy = 0;
if (EGifPutImageDesc(gf, posx, posy, imgs[0]->xsize, imgs[0]->ysize,
opts->interlace, NULL) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image descriptor");
EGifCloseFile(gf);
mm_log((1, "Error in EGifPutImageDesc."));
return 0;
if (EGifPutImageDesc(gf, posx, posy,
imgs[imgn]->xsize, imgs[imgn]->ysize,
opts->interlace, NULL) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not save image descriptor");
myfree(result);
EGifCloseFile(gf);
mm_log((1, "Error in EGifPutImageDesc."));
}
}
if (EGifCloseFile(gf) == GIF_ERROR) {
+ gif_push_error();
+ i_push_error(0, "Could not close GIF file");
mm_log((1, "Error in EGifCloseFile\n"));
return 0;
}
i_gif_opts *opts) {
GifFileType *gf;
+ i_clear_error();
mm_log((1, "i_writegif_gen(quant %p, fd %d, imgs %p, count %d, opts %p)\n",
quant, fd, imgs, count, opts));
gif_set_version(quant, opts);
- mm_log((1, "i_writegif_gen: set ops\n"));
-
if ((gf = EGifOpenFileHandle(fd)) == NULL) {
+ gif_push_error();
+ i_push_error(0, "Cannot create GIF file object");
mm_log((1, "Error in EGifOpenFileHandle, unable to write image.\n"));
+ gif_push_error();
return 0;
}
extern GifFileType *EGifOpen(void *userData, OutputFunc writeFunc);
int result;
+ i_clear_error();
+
mm_log((1, "i_writegif_callback(quant %p, i_write_callback_t %p, userdata $p, maxlength %d, imgs %p, count %d, opts %p)\n",
quant, cb, userdata, maxlength, imgs, count, opts));
if ((gf = EGifOpen(gwd, &gif_writer_callback)) == NULL) {
+ gif_push_error();
+ i_push_error(0, "Cannot create GIF file object");
mm_log((1, "Error in EGifOpenFileHandle, unable to write image.\n"));
free_gen_write_data(gwd, 0);
return 0;
#endif
}
+/*
+=item gif_error_msg(int code)
+
+Grabs the most recent giflib error code from GifLastError() and
+returns a string that describes that error.
+
+The returned pointer points to a static buffer, either from a literal
+C string or a static buffer.
+
+=cut */
+
+static char const *gif_error_msg(int code) {
+ static char msg[80];
+
+ switch (code) {
+ case E_GIF_ERR_OPEN_FAILED: /* should not see this */
+ return "Failed to open given file";
+
+ case E_GIF_ERR_WRITE_FAILED:
+ return "Write failed";
+
+ case E_GIF_ERR_HAS_SCRN_DSCR: /* should not see this */
+ return "Screen descriptor already passed to giflib";
+
+ case E_GIF_ERR_HAS_IMAG_DSCR: /* should not see this */
+ return "Image descriptor already passed to giflib";
+
+ case E_GIF_ERR_NO_COLOR_MAP: /* should not see this */
+ return "Neither global nor local color map set";
+
+ case E_GIF_ERR_DATA_TOO_BIG: /* should not see this */
+ return "Too much pixel data passed to giflib";
+
+ case E_GIF_ERR_NOT_ENOUGH_MEM:
+ return "Out of memory";
+
+ case E_GIF_ERR_DISK_IS_FULL:
+ return "Disk is full";
+
+ case E_GIF_ERR_CLOSE_FAILED: /* should not see this */
+ return "File close failed";
+
+ case E_GIF_ERR_NOT_WRITEABLE: /* should not see this */
+ return "File not writable";
+
+ case D_GIF_ERR_OPEN_FAILED:
+ return "Failed to open file";
+
+ case D_GIF_ERR_READ_FAILED:
+ return "Failed to read from file";
+
+ case D_GIF_ERR_NOT_GIF_FILE:
+ return "File is not a GIF file";
+
+ case D_GIF_ERR_NO_SCRN_DSCR:
+ return "No screen descriptor detected - invalid file";
+
+ case D_GIF_ERR_NO_IMAG_DSCR:
+ return "No image descriptor detected - invalid file";
+
+ case D_GIF_ERR_NO_COLOR_MAP:
+ return "No global or local color map found";
+
+ case D_GIF_ERR_WRONG_RECORD:
+ return "Wrong record type detected - invalid file?";
+
+ case D_GIF_ERR_DATA_TOO_BIG:
+ return "Data in file too big for image";
+
+ case D_GIF_ERR_NOT_ENOUGH_MEM:
+ return "Out of memory";
+
+ case D_GIF_ERR_CLOSE_FAILED:
+ return "Close failed";
+
+ case D_GIF_ERR_NOT_READABLE:
+ return "File not opened for read";
+
+ case D_GIF_ERR_IMAGE_DEFECT:
+ return "Defective image";
+
+ case D_GIF_ERR_EOF_TOO_SOON:
+ return "Unexpected EOF - invalid file";
+
+ default:
+ sprintf(msg, "Unknown giflib error code %d", code);
+ return msg;
+ }
+}
+
+/*
+=item gif_push_error()
+
+Utility function that takes the current GIF error code, converts it to
+an error message and pushes it on the error stack.
+
+=cut
+*/
+
+static void gif_push_error() {
+ int code = GifLastError(); /* clears saved error */
+
+ i_push_error(code, gif_error_msg(code));
+}
+
/*
=head1 BUGS