]> git.imager.perl.org - imager.git/commitdiff
[rt #79029] add support for giflib 5.0
authorTony Cook <tony@develop-help.com>
Thu, 23 Aug 2012 12:59:13 +0000 (22:59 +1000)
committerTony Cook <tony@develop-help.com>
Tue, 11 Sep 2012 10:11:24 +0000 (20:11 +1000)
Changes
GIF/Changes
GIF/Makefile.PL
GIF/imgif.c
GIF/t/t10gif.t

diff --git a/Changes b/Changes
index 5aae5f090b541a7d52670eded77ddddd16893643..86f61e118a72c313ce525b510cf241abd17f4f88 100644 (file)
--- 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
 ===========
 
index a854d3e12b2e8dfd725073c26ac9f91a4ba83b2d..dfc8de7ef66b76b69c3c72c3fe826c5f07434981 100644 (file)
@@ -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
index 0640ba326df8a3908e587b354deed92a0bbc62aa..378dd435eef6db190b527b30062bd5b207321dff 100644 (file)
@@ -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 " */
index 3302d4837b1ddfea4e0768683f3a049c8fe73895..506e10054ae1fbf6744d82a1e9e8d7d8f0c3817a 100644 (file)
@@ -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<gif_set_version> for an explanation.
-
 =head1 AUTHOR
 
 Arnar M. Hrafnkelsson, addi@umich.edu
index c926b0c6bcfe787f21b7a10e36dc6ba0d23b7642..b766f81e290f03fd99f857016935c6ed38de05dc 100644 (file)
@@ -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