~exec64/imv#55: 
Incompatible with libnsgif-1.0.0

Arch Linux recently updated libnsgif from 0.2.1 to 1.0.0 and having read the header files the 1.0.0 is not backwards compatible. This project will eventually have to be updated.

Status
REPORTED
Submitter
unit73e
Assigned to
No-one
Submitted
1 year, 4 months ago
Updated
3 months ago
Labels
No labels applied.

~guttermonk 10 months ago

Animated gifs are disabled on NixOS until this issue is resolved.

See here for more info: https://github.com/NixOS/nixpkgs/blob/194846768975b7ad2c4988bdb82572c00222c0d7/pkgs/applications/graphics/imv/default.nix#L19

Long Huynh Huu 3 months ago ยท edit

I've written a patch for v4.5.0 that bumps the libnsgif version to 1.0.0 as well as some required adjustments. I'm by no means well-versed in C so this patch requires some careful scrutiny I am not able to provide myself.

~cornservant 3 months ago*

Apparently using attachments doesn't work, so here's the diff:

Edit: fixed a memory leak

diff --git a/meson.build b/meson.build
index ea3a653..69127f8 100644
--- a/meson.build
+++ b/meson.build
@@ -125,7 +125,7 @@ foreach backend : [
   ['libpng', 'dependency', 'libpng', []],
   ['libjpeg', 'dependency', 'libturbojpeg', []],
   ['librsvg', 'dependency', 'librsvg-2.0', '>= 2.44'],
-  ['libnsgif', 'dependency', 'libnsgif', '< 1.0.0'],
+  ['libnsgif', 'dependency', 'libnsgif', '>= 1.0.0'],
   ['libheif', 'dependency', 'libheif', []],
   ['libjxl', 'dependency', 'libjxl', []],
 ]
diff --git a/src/backend_libnsgif.c b/src/backend_libnsgif.c
index 5c5995b..f02f34a 100644
--- a/src/backend_libnsgif.c
+++ b/src/backend_libnsgif.c
@@ -6,7 +6,7 @@
 #include "source_private.h"
 
 #include <fcntl.h>
-#include <libnsgif.h>
+#include <nsgif.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
@@ -14,7 +14,7 @@
 
 struct private {
   int current_frame;
-  gif_animation gif;
+  nsgif_t *gif;
   void *data;
   size_t len;
 };
@@ -52,7 +52,7 @@ static void bitmap_mark_modified(void *bitmap)
   (void)bitmap;
 }
 
-static gif_bitmap_callback_vt bitmap_callbacks = {
+static nsgif_bitmap_cb_vt bitmap_callbacks = {
   bitmap_create,
   bitmap_destroy,
   bitmap_get_buffer,
@@ -69,7 +69,7 @@ static void free_private(void *raw_private)
   }
 
   struct private *private = raw_private;
-  gif_finalise(&private->gif);
+  nsgif_destroy(private->gif);
   munmap(private->data, private->len);
   free(private);
 }
@@ -78,15 +78,28 @@ static void push_current_image(struct private *private,
     struct imv_image **image, int *frametime)
 {
   struct imv_bitmap *bmp = malloc(sizeof *bmp);
-  bmp->width = private->gif.width;
-  bmp->height = private->gif.height;
+  bmp->width = nsgif_get_info(private->gif)->width;
+  bmp->height = nsgif_get_info(private->gif)->height;
   bmp->format = IMV_ABGR;
   size_t len = 4 * bmp->width * bmp->height;
   bmp->data = malloc(len);
-  memcpy(bmp->data, private->gif.frame_image, len);
+
+  nsgif_bitmap_t *frame = 0;
+
+  nsgif_error code =
+      nsgif_frame_decode(private->gif, private->current_frame, &frame);
+
+  if (code != NSGIF_OK) {
+    imv_log(IMV_DEBUG, "libnsgif: failed to decode frame %d\n",
+            private->current_frame);
+    return;
+  }
+
+  memcpy(bmp->data, frame, len);
 
   *image = imv_image_create_from_bitmap(bmp);
-  *frametime = private->gif.frames[private->current_frame].frame_delay * 10.0;
+  *frametime =
+      nsgif_get_frame_info(private->gif, private->current_frame)->delay * 10.0;
 }
 
 static void first_frame(void *raw_private, struct imv_image **image, int *frametime)
@@ -97,12 +110,6 @@ static void first_frame(void *raw_private, struct imv_image **image, int *framet
   struct private *private = raw_private;
   private->current_frame = 0;
 
-  gif_result code = gif_decode_frame(&private->gif, private->current_frame);
-  if (code != GIF_OK) {
-    imv_log(IMV_DEBUG, "libnsgif: failed to decode first frame\n");
-    return;
-  }
-
   push_current_image(private, image, frametime);
 }
 
@@ -114,13 +121,7 @@ static void next_frame(void *raw_private, struct imv_image **image, int *frameti
   struct private *private = raw_private;
 
   private->current_frame++;
-  private->current_frame %= private->gif.frame_count;
-
-  gif_result code = gif_decode_frame(&private->gif, private->current_frame);
-  if (code != GIF_OK) {
-    imv_log(IMV_DEBUG, "libnsgif: failed to decode a frame\n");
-    return;
-  }
+  private->current_frame %= nsgif_get_info(private->gif)->frame_count;
 
   push_current_image(private, image, frametime);
 }
@@ -134,20 +135,19 @@ static const struct imv_source_vtable vtable = {
 static enum backend_result open_memory(void *data, size_t len, struct imv_source **src)
 {
   struct private *private = calloc(1, sizeof *private);
-  gif_create(&private->gif, &bitmap_callbacks);
+  nsgif_create(&bitmap_callbacks, 0, &private->gif);
 
-  gif_result code;
-  do {
-    code = gif_initialise(&private->gif, len, data);
-  } while (code == GIF_WORKING);
+  nsgif_error code = nsgif_data_scan(private->gif, len, data);
 
-  if (code != GIF_OK) {
-    gif_finalise(&private->gif);
+  if (code != NSGIF_OK) {
+    nsgif_destroy(private->gif);
     free(private);
     imv_log(IMV_DEBUG, "libsngif: unsupported file\n");
     return BACKEND_UNSUPPORTED;
   }
 
+  nsgif_data_complete(private->gif);
+
   *src = imv_source_create(&vtable, private);
   return BACKEND_SUCCESS;
 }
@@ -176,24 +176,26 @@ static enum backend_result open_path(const char *path, struct imv_source **src)
   struct private *private = calloc(1, sizeof *private);
   private->data = data;
   private->len = len;
-  gif_create(&private->gif, &bitmap_callbacks);
+  nsgif_create(&bitmap_callbacks, NSGIF_BITMAP_FMT_R8G8B8A8, &private->gif);
 
-  gif_result code;
-  do {
-    code = gif_initialise(&private->gif, private->len, private->data);
-  } while (code == GIF_WORKING);
+  nsgif_error code = nsgif_data_scan(private->gif, private->len, private->data);
 
-  if (code != GIF_OK) {
-    gif_finalise(&private->gif);
+  if (code != NSGIF_OK) {
+    nsgif_destroy(private->gif);
     munmap(private->data, private->len);
     free(private);
     imv_log(IMV_DEBUG, "libsngif: unsupported file\n");
     return BACKEND_UNSUPPORTED;
   }
 
-  imv_log(IMV_DEBUG, "libnsgif: num_frames=%d\n", private->gif.frame_count);
-  imv_log(IMV_DEBUG, "libnsgif: width=%d\n", private->gif.width);
-  imv_log(IMV_DEBUG, "libnsgif: height=%d\n", private->gif.height);
+  nsgif_data_complete(private->gif);
+
+  imv_log(IMV_DEBUG, "libnsgif: num_frames=%d\n",
+          nsgif_get_info(private->gif)->frame_count);
+  imv_log(IMV_DEBUG, "libnsgif: width=%d\n",
+          nsgif_get_info(private->gif)->width);
+  imv_log(IMV_DEBUG, "libnsgif: height=%d\n",
+          nsgif_get_info(private->gif)->height);
 
   *src = imv_source_create(&vtable, private);
   return BACKEND_SUCCESS;
Register here or Log in to comment, or comment via email.