Package: nsxiv
Version: 29-2
Severity: normal
Tags: patch

First of all thanks for packaging nsxiv for debian.

as the subject indicates, nsxiv fails to even load animated webp images this is
intended as v29 depends on imlib2 1.7.5 for animated webp support, this reverts
the webp function to the older version that works with 1.7.1, in the future the
plan for nsxiv is to depend on 1.8.0 to handle multi frame images, altho the
change was intended for v30 it is currenlty on hold as it causes performance
regressions.

i tested and the patch works as expected.

>From 407052d02f01ac2a345edc651dc5a791e81eb5fc Mon Sep 17 00:00:00 2001
From: eylles <ed.ylles1...@gmail.com>
Date: Thu, 21 Apr 2022 03:12:24 -0600
Subject: [PATCH] Restore old webp loading

Use webp loading function for imlib2 1.7.1 (and possibly 1.6.9)
This reverts upstream commits:
61da0a8ca9f2a39042f7ef9af63a2dd48057c927
b0b16f1d0ffa550a8358206de844c9cf13f94ada
22ca3b567dd08c0086399221cb1413fa4eb74e2e
3b6db44267438fb0f9d67b3783d3bc6713c3c07f
eccd7de532b09fb738638095675eefc7be96ecc3


---
 README.md |   1 -
 image.c   | 162 +++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 104 insertions(+), 59 deletions(-)

diff --git a/README.md b/README.md
index c5028ac..b939366 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,6 @@ The following dependencies are optional.
   * libexif : Used for auto-orientation and exif thumbnails.
     Disable via `HAVE_LIBEXIF=0`
   * libwebp : Used for animated webp playback.
-    (NOTE: animated webp also requires Imlib2 v1.7.5 or above)
     Disabled via `HAVE_LIBWEBP=0`.

 Please make sure to install the corresponding development packages in case that
diff --git a/image.c b/image.c
index 1c57d27..ade5d1b 100644
--- a/image.c
+++ b/image.c
@@ -135,23 +135,6 @@ void exif_auto_orientate(const fileinfo_t *file)
 }
 #endif

-#if HAVE_LIBGIF || HAVE_LIBWEBP
-static void img_multiframe_context_set(img_t *img)
-{
-       if (img->multi.cnt > 1) {
-               imlib_context_set_image(img->im);
-               imlib_free_image();
-               img->im = img->multi.frames[0].im;
-       } else if (img->multi.cnt == 1) {
-               imlib_context_set_image(img->multi.frames[0].im);
-               imlib_free_image();
-               img->multi.cnt = 0;
-       }
-
-       imlib_context_set_image(img->im);
-}
-#endif
-
 #if HAVE_LIBGIF
 static bool img_load_gif(img_t *img, const fileinfo_t *file)
 {
@@ -315,7 +298,17 @@ static bool img_load_gif(img_t *img, const fileinfo_t 
*file)
        if (err && (file->flags & FF_WARN))
                error(0, 0, "%s: Corrupted gif file", file->name);

-       img_multiframe_context_set(img);
+       if (img->multi.cnt > 1) {
+               imlib_context_set_image(img->im);
+               imlib_free_image();
+               img->im = img->multi.frames[0].im;
+       } else if (img->multi.cnt == 1) {
+               imlib_context_set_image(img->multi.frames[0].im);
+               imlib_free_image();
+               img->multi.cnt = 0;
+       }
+
+       imlib_context_set_image(img->im);

        return !err;
 }
@@ -323,35 +316,60 @@ static bool img_load_gif(img_t *img, const fileinfo_t 
*file)


 #if HAVE_LIBWEBP
-static bool img_load_webp(img_t *img, const fileinfo_t *file)
+static bool is_webp(const char *path)
+{
+       /* The size (in bytes) of the largest amount of data required to verify 
a WebP image. */
+       enum { max = 30 };
+       const unsigned char fmt[max];
+       bool ret = false;
+       FILE *f;
+
+       if ((f = fopen(path, "rb")) != NULL) {
+               if (fread((unsigned char *) fmt, 1, max, f) == max)
+                       ret = WebPGetInfo(fmt, max, NULL, NULL);
+               fclose(f);
+       }
+       return ret;
+}
+
+/* fframe   img
+ * NULL     NULL  = do nothing
+ * x        NULL  = load the first frame as an Imlib_Image
+ * NULL     x     = load all frames into img->multi.
+ */
+static bool img_load_webp(const fileinfo_t *file, Imlib_Image *fframe, img_t 
*img)
 {
        FILE *webp_file;
        WebPData data;
+
        Imlib_Image im = NULL;
        struct WebPAnimDecoderOptions opts;
        WebPAnimDecoder *dec = NULL;
        struct WebPAnimInfo info;
-       unsigned char *buf = NULL, *bytes = NULL;
+       unsigned char *buf = NULL;
        int ts;
        const WebPDemuxer *demux;
        WebPIterator iter;
        unsigned long flags;
        unsigned int delay;
        bool err = false;
+       data.bytes = NULL;

-       if ((webp_file = fopen(file->path, "rb")) == NULL) {
-               error(0, errno, "%s: Error opening webp image", file->name);
-               return false;
+       if ((err = fframe == NULL && img == NULL))
+               goto fail;
+
+       if ((err = (webp_file = fopen(file->path, "rb")) == NULL)) {
+               error(0, 0, "%s: Error opening webp image", file->name);
+               goto fail;
        }
        fseek(webp_file, 0L, SEEK_END);
        data.size = ftell(webp_file);
        rewind(webp_file);
-       bytes = emalloc(data.size);
-       if ((err = fread(bytes, 1, data.size, webp_file) != data.size)) {
+       data.bytes = emalloc(data.size);
+       if ((err = fread((unsigned char *)data.bytes, 1, data.size, webp_file) 
!= data.size)) {
                error(0, 0, "%s: Error reading webp image", file->name);
                goto fail;
        }
-       data.bytes = bytes;

        /* Setup the WebP Animation Decoder */
        if ((err = !WebPAnimDecoderOptionsInit(&opts))) {
@@ -368,42 +386,65 @@ static bool img_load_webp(img_t *img, const fileinfo_t 
*file)
        }
        demux = WebPAnimDecoderGetDemuxer(dec);

-       /* Get global information for the image */
-       flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
-       img->w = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
-       img->h = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
+       if (img == NULL) { /* Only get the first frame and put it into fframe. 
*/
+               if ((err = !WebPAnimDecoderGetNext(dec, &buf, &ts))) {
+                       error(0, 0, "%s: Error loading first frame", 
file->name);
+                       goto fail;
+               }
+               *fframe = imlib_create_image_using_copied_data(
+                         info.canvas_width, info.canvas_height, (DATA32*)buf);
+               imlib_context_set_image(*fframe);
+               imlib_image_set_has_alpha(WebPDemuxGetI(demux, 
WEBP_FF_FORMAT_FLAGS) & ALPHA_FLAG);
+       } else {
+               /* Get global information for the image */
+               flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
+               img->w = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
+               img->h = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
+
+               if (img->multi.cap == 0) {
+                       img->multi.cap = info.frame_count;
+                       img->multi.frames = emalloc(img->multi.cap * 
sizeof(img_frame_t));
+               } else if (info.frame_count > img->multi.cap) {
+                       img->multi.cap = info.frame_count;
+                       img->multi.frames = erealloc(img->multi.frames,
+                                                    img->multi.cap * 
sizeof(img_frame_t));
+               }

-       if (info.frame_count > img->multi.cap) {
-               img->multi.cap = info.frame_count;
-               img->multi.frames = erealloc(img->multi.frames,
-                                            img->multi.cap * 
sizeof(img_frame_t));
-       }
+               /* Load and decode frames (also works on images with only 1 
frame) */
+               img->multi.cnt = img->multi.sel = 0;
+               while (WebPAnimDecoderGetNext(dec, &buf, &ts)) {
+                       im = imlib_create_image_using_copied_data(
+                            info.canvas_width, info.canvas_height, 
(DATA32*)buf);
+                       imlib_context_set_image(im);
+                       imlib_image_set_format("webp");
+                       /* Get an iterator of this frame - used for frame info 
(duration, etc.) */
+                       WebPDemuxGetFrame(demux, img->multi.cnt+1, &iter);
+                       imlib_image_set_has_alpha((flags & ALPHA_FLAG) == 
ALPHA_FLAG);
+                       /* Store info for this frame */
+                       img->multi.frames[img->multi.cnt].im = im;
+                       delay = iter.duration > 0 ? iter.duration : 
DEF_WEBP_DELAY;
+                       img->multi.frames[img->multi.cnt].delay = delay;
+                       img->multi.length += 
img->multi.frames[img->multi.cnt].delay;
+                       img->multi.cnt++;
+               }
+               WebPDemuxReleaseIterator(&iter);

-       /* Load and decode frames (also works on images with only 1 frame) */
-       img->multi.cnt = img->multi.sel = 0;
-       while (WebPAnimDecoderGetNext(dec, &buf, &ts)) {
-               im = imlib_create_image_using_copied_data(
-                    info.canvas_width, info.canvas_height, (DATA32*)buf);
-               imlib_context_set_image(im);
-               imlib_image_set_format("webp");
-               /* Get an iterator of this frame - used for frame info 
(duration, etc.) */
-               WebPDemuxGetFrame(demux, img->multi.cnt+1, &iter);
-               imlib_image_set_has_alpha((flags & ALPHA_FLAG) == ALPHA_FLAG);
-               /* Store info for this frame */
-               img->multi.frames[img->multi.cnt].im = im;
-               delay = iter.duration > 0 ? iter.duration : DEF_WEBP_DELAY;
-               img->multi.frames[img->multi.cnt].delay = delay;
-               img->multi.length += img->multi.frames[img->multi.cnt].delay;
-               img->multi.cnt++;
+               if (img->multi.cnt > 1) {
+                       imlib_context_set_image(img->im);
+                       imlib_free_image();
+                       img->im = img->multi.frames[0].im;
+               } else if (img->multi.cnt == 1) {
+                       imlib_context_set_image(img->multi.frames[0].im);
+                       imlib_free_image();
+                       img->multi.cnt = 0;
+               }
+               imlib_context_set_image(img->im);
        }
-       WebPDemuxReleaseIterator(&iter);
-
-       img_multiframe_context_set(img);
+       imlib_image_set_format("webp");
 fail:
        if (dec != NULL)
                WebPAnimDecoderDelete(dec);
-       free(bytes);
-       fclose(webp_file);
+       free((unsigned char *)data.bytes);
        return !err;
 }
 #endif /* HAVE_LIBWEBP */
@@ -416,7 +457,12 @@ Imlib_Image img_open(const fileinfo_t *file)
        if (access(file->path, R_OK) == 0 &&
            stat(file->path, &st) == 0 && S_ISREG(st.st_mode))
        {
-               im = imlib_load_image(file->path);
+#if HAVE_LIBWEBP
+               if (is_webp(file->path))
+                       img_load_webp(file, &im, NULL);
+               else
+#endif
+                       im = imlib_load_image(file->path);
                if (im != NULL) {
                        imlib_context_set_image(im);
                        if (imlib_image_get_data_for_reading_only() == NULL) {
@@ -454,7 +500,7 @@ bool img_load(img_t *img, const fileinfo_t *file)
 #endif
 #if HAVE_LIBWEBP
                if (STREQ(fmt, "webp"))
-                       img_load_webp(img, file);
+                       img_load_webp(file, NULL, img);
 #endif
 #if HAVE_LIBEXIF && defined(IMLIB2_VERSION)
                if (!STREQ(fmt, "jpeg") && !STREQ(fmt, "jpg"))


-- System Information:
Debian Release: bookworm/sid
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.16.0-6-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US:en
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)
LSM: AppArmor: enabled

Versions of packages nsxiv depends on:
ii  libc6           2.33-7
ii  libexif12       0.6.24-1
ii  libfontconfig1  2.13.1-4.4
ii  libgif7         5.1.9-2
ii  libimlib2       1.7.4-2
ii  libwebpdemux2   1.2.2-2+b1
ii  libx11-6        2:1.7.5-1
ii  libxft2         2.3.4-1

nsxiv recommends no packages.

Versions of packages nsxiv suggests:
ii  graphicsmagick-imagemagick-compat [imagemagick]  1.4+really1.3.38-1
pn  libjpeg-progs                                    <none>
pn  rawtherapee                                      <none>
ii  xclip                                            0.13-2

-- no debconf information

Reply via email to