From: Tony Cook Date: Thu, 23 Aug 2012 12:59:13 +0000 (+1000) Subject: [rt #79029] add support for giflib 5.0 X-Git-Tag: v0.93~32 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/4224d05d85130a06f9b32f15e38ed662ed5b1fd5 [rt #79029] add support for giflib 5.0 --- diff --git a/Changes b/Changes index 5aae5f09..86f61e11 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,9 @@ Imager release history. Older releases can be found in Changes.old - improve error reporting - provide better control of the level of anti-aliasing + - support for giflib 5.0. + https://rt.cpan.org/Ticket/Display.html?id=79029 + Imager 0.92 - 14 Aug 2012 =========== diff --git a/GIF/Changes b/GIF/Changes index a854d3e1..dfc8de7e 100644 --- a/GIF/Changes +++ b/GIF/Changes @@ -1,4 +1,10 @@ -Imager-File-GIF 0.84 +Imager-File-GIF 0.85 +==================== + + - add giflib 5.0 support. + https://rt.cpan.org/Ticket/Display.html?id=79029 + +Imager-File-GIF 0.84 - released with Imager 0.92_01 ==================== - giflib 4.2 eliminates the GIF_LIB_VERSION macro, handle that diff --git a/GIF/Makefile.PL b/GIF/Makefile.PL index 0640ba32..378dd435 100644 --- a/GIF/Makefile.PL +++ b/GIF/Makefile.PL @@ -74,7 +74,7 @@ my %probe = inccheck => sub { -e File::Spec->catfile($_[0], "gif_lib.h") }, libbase => "gif", testcode => _gif_test_code(), - testcodeheaders => [ "gif_lib.h", "stdio.h" ], + testcodeheaders => [ "stddef.h", "gif_lib.h", "stdio.h" ], incpath => \@incpaths, libpath => \@libpaths, ); @@ -119,8 +119,13 @@ int ver_min; #else int ver_maj = GIFLIB_MAJOR; int ver_min = GIFLIB_MINOR; +int error; #endif +#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 +gf=DGifOpenFileName("testimg/expected.gif", &error); +#else gf=DGifOpenFileName("testimg/expected.gif"); +#endif if (!gf) { fprintf(stderr, "GIF: Cannot open testimg/expected.gif\n"); return 1; @@ -129,9 +134,11 @@ if (gf->SWidth != 16 || gf->SHeight != 16) { fprintf(stderr, "GIF: bad screen description (%d x %d)\n", gf->SWidth, gf->SHeight); return 1; } -/* crashes in older versions of giflib */ +#if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5 +/* crashes in older versions of giflib, not used in giflib 5 */ EGifSetGifVersion("89a"); EGifSetGifVersion("87a"); +#endif #ifdef GIF_LIB_VERSION /* skip the " Version " */ diff --git a/GIF/imgif.c b/GIF/imgif.c index 3302d483..506e1005 100644 --- a/GIF/imgif.c +++ b/GIF/imgif.c @@ -59,21 +59,69 @@ functionality with giflib3. =cut */ +#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 +#define myDGifOpen(userPtr, readFunc, Error) DGifOpen((userPtr), (readFunc), (Error)) +#define myEGifOpen(userPtr, readFunc, Error) EGifOpen((userPtr), (readFunc), (Error)) +#define myGifError(gif) ((gif)->Error) +#define MakeMapObject GifMakeMapObject +#define FreeMapObject GifFreeMapObject + +#define gif_mutex_lock() +#define gif_mutex_unlock() +#else +static GifFileType * +myDGifOpen(void *userPtr, InputFunc readFunc, int *error) { + GifFileType *result = DGifOpen(userPtr, readFunc); + if (!result) + *error = GifLastError(); + + return result; +} +static GifFileType * +myEGifOpen(void *userPtr, OutputFunc outputFunc, int *error) { + GifFileType *result = EGifOpen(userPtr, outputFunc); + if (!result) + *error = GifLastError(); + + return result; +} +#define myGifError(gif) GifLastError() + +#define gif_mutex_lock() i_mutex_lock(mutex) +#define gif_mutex_unlock() i_mutex_unlock(mutex) +#define NEED_MUTEX +#endif + static char const *gif_error_msg(int code); -static void gif_push_error(void); +static void gif_push_error(int code); /* Make some variables global, so we could access them faster: */ -static int +static const int InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */ InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ +#ifdef NEED_MUTEX static i_mutex_t mutex; +#endif + +/* +=item i_init_gif() + +Initialize GIF support. + +For versions of giflib that require it, create a mutex to avoid +reentrancy. + +=cut +*/ void i_init_gif(void) { +#ifdef NEED_MUTEX mutex = i_mutex_new(); +#endif } static @@ -144,7 +192,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { GifByteType *Extension; GifRowType GifRow; - static GifColorType *ColorMapEntry; + GifColorType *ColorMapEntry; i_color col; mm_log((1,"i_readgif_low(GifFile %p, colour_table %p, colours %p)\n", GifFile, colour_table, colours)); @@ -193,7 +241,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Unable to get record type"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -208,7 +256,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Unable to get image descriptor"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -262,7 +310,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) { Count++; if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading GIF line"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -287,7 +335,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { else { for (i = 0; i < Height; i++) { if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading GIF line"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -313,7 +361,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading extension record"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -326,7 +374,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { } while (Extension != NULL) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "reading next block of extension"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -349,7 +397,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { myfree(GifRow); if (DGifCloseFile(GifFile) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Closing GIF file object"); if (colour_table && *colour_table) { myfree(*colour_table); @@ -369,7 +417,8 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) { Internal function called by i_readgif_multi_low() in error handling */ -static void free_images(i_img **imgs, int count) { +static void +free_images(i_img **imgs, int count) { int i; if (count) { @@ -463,7 +512,8 @@ standard. =cut */ -i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { +i_img ** +i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { i_img *img; int i, j, Size, Width, Height, ExtCode, Count; int ImageNum = 0, BackGround = 0, ColorMapSize = 0; @@ -503,7 +553,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Unable to get record type"); free_images(results, *count); DGifCloseFile(GifFile); @@ -516,7 +566,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Unable to get image descriptor"); free_images(results, *count); DGifCloseFile(GifFile); @@ -649,7 +699,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { j += InterlacedJumps[i]) { Count++; if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading GIF line"); free_images(results, *count); DGifCloseFile(GifFile); @@ -678,7 +728,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { else { for (i = 0; i < Height; i++) { if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading GIF line"); free_images(results, *count); DGifCloseFile(GifFile); @@ -719,7 +769,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { /* giflib does't have an interface to skip the image data */ for (i = 0; i < Height; i++) { if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading GIF line"); free_images(results, *count); myfree(GifRow); @@ -741,7 +791,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Reading extension record"); free_images(results, *count); myfree(GifRow); @@ -766,7 +816,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { if (ExtCode == 0xFF && *Extension == 11) { if (memcmp(Extension+1, "NETSCAPE2.0", 11) == 0) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "reading loop extension"); free_images(results, *count); myfree(GifRow); @@ -796,7 +846,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { } while (Extension != NULL) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "reading next block of extension"); free_images(results, *count); myfree(GifRow); @@ -825,7 +875,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) { myfree(GifRow); if (DGifCloseFile(GifFile) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(GifFile)); i_push_error(0, "Closing GIF file object"); free_images(results, *count); return NULL; @@ -853,22 +903,23 @@ i_img ** i_readgif_multi_wiol(io_glue *ig, int *count) { GifFileType *GifFile; i_img **result; + int gif_error; - i_mutex_lock(mutex); + gif_mutex_lock(); i_clear_error(); - if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) { - gif_push_error(); + if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) { + gif_push_error(gif_error); i_push_error(0, "Cannot create giflib callback object"); mm_log((1,"i_readgif_multi_wiol: Unable to open callback datasource.\n")); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return NULL; } result = i_readgif_multi_low(GifFile, count, -1); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return result; } @@ -884,22 +935,23 @@ i_img * i_readgif_wiol(io_glue *ig, int **color_table, int *colors) { GifFileType *GifFile; i_img *result; + int gif_error; - i_mutex_lock(mutex); + gif_mutex_lock(); i_clear_error(); - if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) { - gif_push_error(); + if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) { + gif_push_error(gif_error); i_push_error(0, "Cannot create giflib callback object"); mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n")); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return NULL; } result = i_readgif_low(GifFile, color_table, colors); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return result; } @@ -947,6 +999,7 @@ i_img * i_readgif_single_wiol(io_glue *ig, int page) { GifFileType *GifFile; i_img *result; + int gif_error; i_clear_error(); if (page < 0) { @@ -954,19 +1007,19 @@ i_readgif_single_wiol(io_glue *ig, int page) { return NULL; } - i_mutex_lock(mutex); + gif_mutex_lock(); - if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) { - gif_push_error(); + if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) { + gif_push_error(gif_error); i_push_error(0, "Cannot create giflib callback object"); mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n")); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return NULL; } result = i_readgif_single_low(GifFile, page); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return result; } @@ -988,7 +1041,7 @@ do_write(GifFileType *gf, int interlace, i_img *img, i_palidx *data) { 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(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save image data:"); mm_log((1, "Error in EGifPutLine\n")); EGifCloseFile(gf); @@ -1001,7 +1054,7 @@ do_write(GifFileType *gf, int interlace, i_img *img, i_palidx *data) { int y; for (y = 0; y < img->ysize; ++y) { if (EGifPutLine(gf, data, img->xsize) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save image data:"); mm_log((1, "Error in EGifPutLine\n")); EGifCloseFile(gf); @@ -1023,7 +1076,9 @@ Returns non-zero on success. =cut */ -static int do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index) + +static int +do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index) { unsigned char gce[4] = {0}; int want_gce = 0; @@ -1052,7 +1107,7 @@ static int do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index) } if (want_gce) { if (EGifPutExtension(gf, 0xF9, sizeof(gce), gce) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save GCE"); } } @@ -1066,7 +1121,9 @@ Write any comments in the image. =cut */ -static int do_comments(GifFileType *gf, i_img *img) { + +static int +do_comments(GifFileType *gf, i_img *img) { int pos = -1; while (i_tags_find(&img->tags, "gif_comment", pos+1, &pos)) { @@ -1104,7 +1161,9 @@ writing extension blocks so that they could only be written to files. =cut */ -static int do_ns_loop(GifFileType *gf, i_img *img) + +static int +do_ns_loop(GifFileType *gf, i_img *img) { /* EGifPutExtension() doesn't appear to handle application extension blocks in any way @@ -1121,19 +1180,33 @@ static int do_ns_loop(GifFileType *gf, i_img *img) if (i_tags_get_int(&img->tags, "gif_loop", 0, &loop_count)) { unsigned char nsle[12] = "NETSCAPE2.0"; unsigned char subblock[3]; + + subblock[0] = 1; + subblock[1] = loop_count % 256; + subblock[2] = loop_count / 256; + +#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 + if (EGifPutExtensionLeader(gf, APPLICATION_EXT_FUNC_CODE) == GIF_ERROR + || EGifPutExtensionBlock(gf, 11, nsle) == GIF_ERROR + || EGifPutExtensionBlock(gf, 3, subblock) == GIF_ERROR + || EGifPutExtensionTrailer(gf) == GIF_ERROR) { + gif_push_error(myGifError(gf)); + i_push_error(0, "writing loop extension"); + return 0; + } + +#else if (EGifPutExtensionFirst(gf, APPLICATION_EXT_FUNC_CODE, 11, nsle) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "writing loop extension"); return 0; } - subblock[0] = 1; - subblock[1] = loop_count % 256; - subblock[2] = loop_count / 256; if (EGifPutExtensionLast(gf, APPLICATION_EXT_FUNC_CODE, 3, subblock) == GIF_ERROR) { - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "writing loop extension sub-block"); return 0; } +#endif } return 1; @@ -1147,8 +1220,8 @@ Create a giflib color map object from an Imager color map. =cut */ -static ColorMapObject *make_gif_map(i_quantize *quant, i_img *img, - int want_trans) { +static ColorMapObject * +make_gif_map(i_quantize *quant, i_img *img, int want_trans) { GifColorType colors[256]; int i; int size = quant->mc_count; @@ -1183,7 +1256,6 @@ static ColorMapObject *make_gif_map(i_quantize *quant, i_img *img, map = MakeMapObject(map_size, colors); mm_log((1, "XXX map is at %p and colors at %p\n", map, map->Colors)); if (!map) { - gif_push_error(); i_push_error(0, "Could not create color map object"); return NULL; } @@ -1220,10 +1292,14 @@ If t/t105gif.t crashes here then run Makefile.PL with or install a less buggy giflib. +This code is completely unnecessary in giflib 5 + =cut */ -static void gif_set_version(i_quantize *quant, i_img **imgs, int count) { +static void +gif_set_version(i_quantize *quant, i_img **imgs, int count) { +#if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5 int need_89a = 0; int temp; int i; @@ -1254,6 +1330,7 @@ static void gif_set_version(i_quantize *quant, i_img **imgs, int count) { EGifSetGifVersion("89a"); else EGifSetGifVersion("87a"); +#endif } static int @@ -1536,7 +1613,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) { myfree(localmaps); myfree(glob_imgs); quant->mc_colors = orig_colors; - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save screen descriptor"); FreeMapObject(map); myfree(result); @@ -1644,7 +1721,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) { myfree(localmaps); myfree(glob_imgs); quant->mc_colors = orig_colors; - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save image descriptor"); EGifCloseFile(gf); mm_log((1, "Error in EGifPutImageDesc.")); @@ -1761,7 +1838,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) { myfree(localmaps); myfree(glob_imgs); quant->mc_colors = orig_colors; - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not save image descriptor"); myfree(result); if (map) @@ -1789,7 +1866,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) { myfree(glob_colors); myfree(localmaps); myfree(glob_imgs); - gif_push_error(); + gif_push_error(myGifError(gf)); i_push_error(0, "Could not close GIF file"); mm_log((1, "Error in EGifCloseFile\n")); return 0; @@ -1826,24 +1903,25 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs, int count) { GifFileType *GifFile; int result; + int gif_error; - i_mutex_lock(mutex); + gif_mutex_lock(); i_clear_error(); gif_set_version(quant, imgs, count); - if ((GifFile = EGifOpen((void *)ig, io_glue_write_cb )) == NULL) { - gif_push_error(); + if ((GifFile = myEGifOpen((void *)ig, io_glue_write_cb, &gif_error )) == NULL) { + gif_push_error(gif_error); i_push_error(0, "Cannot create giflib callback object"); mm_log((1,"i_writegif_wiol: Unable to open callback datasource.\n")); - i_mutex_unlock(mutex); + gif_mutex_unlock(); return 0; } result = i_writegif_low(quant, GifFile, imgs, count); - i_mutex_unlock(mutex); + gif_mutex_unlock(); if (i_io_close(ig)) return 0; @@ -1857,15 +1935,16 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs, 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. +Returns NULL for unknown error codes. =cut */ -static char const *gif_error_msg(int code) { - static char msg[80]; - +static char const * +gif_error_msg(int code) { +#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 + return GifErrorString(code); +#else switch (code) { case E_GIF_ERR_OPEN_FAILED: /* should not see this */ return "Failed to open given file"; @@ -1937,17 +2016,13 @@ static char const *gif_error_msg(int code) { return "Unexpected EOF - invalid file"; default: -#ifdef IMAGER_SNPRINTF - snprintf(msg, sizeof(msg), "Unknown giflib error code %d", code); -#else - sprintf(msg, "Unknown giflib error code %d", code); -#endif - return msg; + return NULL; } +#endif } /* -=item gif_push_error() +=item gif_push_error(code) Utility function that takes the current GIF error code, converts it to an error message and pushes it on the error stack. @@ -1955,27 +2030,16 @@ an error message and pushes it on the error stack. =cut */ -static void gif_push_error(void) { - int code = GifLastError(); /* clears saved error */ - - i_push_error(code, gif_error_msg(code)); +static void +gif_push_error(int code) { + const char *msg = gif_error_msg(code); + if (msg) + i_push_error(code, msg); + else + i_push_errorf(code, "Unknown GIF error %d", code); } /* -=head1 BUGS - -The Netscape loop extension isn't implemented. Giflib's extension -writing code doesn't seem to support writing named extensions in this -form. - -A bug in giflib is tickled by the i_writegif_callback(). This isn't a -problem on ungiflib, but causes a SEGV on giflib. A patch is provided -in t/t10formats.t - -The GIF file tag (GIF87a vs GIF89a) currently isn't set. Using the -supplied interface in giflib 4.1.0 causes a SEGV in -EGifSetGifVersion(). See L for an explanation. - =head1 AUTHOR Arnar M. Hrafnkelsson, addi@umich.edu diff --git a/GIF/t/t10gif.t b/GIF/t/t10gif.t index c926b0c6..b766f81e 100644 --- a/GIF/t/t10gif.t +++ b/GIF/t/t10gif.t @@ -404,7 +404,8 @@ read_failure('testimg/nocmap.gif'); ($io, { make_colors=>'addi', translate=>'closest', transp=>'ordered', - }, @imgs), "write from paletted"); + }, @imgs), "write from paletted") + or diag(Imager->_error_as_msg()); close FH; # make sure nothing bad happened