GNU bug report logs - #54242
Emacs can't display animated webp images

Previous Next

Package: emacs;

Reported by: Jean Louis <bugs <at> gnu.support>

Date: Fri, 4 Mar 2022 07:15:01 UTC

Severity: normal

Found in version 29.0.50

Fixed in version 29.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Jean Louis <bugs <at> gnu.support>
Cc: 54242 <at> debbugs.gnu.org
Subject: bug#54242: Emacs can't display animated webp images
Date: Thu, 07 Apr 2022 16:42:44 +0200
[Message part 1 (text/plain, inline)]
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> Here's an example animated webp image, and indeed, Emacs fails at
> displaying it:
>
> https://mathiasbynens.be/demo/animated-webp-supported.webp

I've started poking at this just to see what's necessary.  As a first
attempt, I thought we could at least display the first frame in the
animate image, so I did the following according to the er documentation
from Google.

[Message part 2 (image/png, inline)]
[Message part 3 (text/plain, inline)]
And indeed, I end up with something that looks like a mangled version of
the nyan cat in the test URL above -- but with wrong width and height or
something?  

The first image in the animation is very simple, though -- frame
width/height is the same as the canvas width height...  so I must be
doing something obviously wrong:

Data: 400 400 400 400 0 0

Anybody spot the obvious error?

There's also the "animation" functions from libwebp, but they are even
less clear as to how they're supposed to be used.

Amusingly, imagemagick also renders the animated webp image wrong, but
in a different way.

diff --git a/configure.ac b/configure.ac
index cda2a04be9..fc409ce8f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2692,6 +2692,7 @@ AC_DEFUN
 
       EMACS_CHECK_MODULES([WEBP], [$WEBP_MODULE])
       AC_SUBST(WEBP_CFLAGS)
+      WEBP_LIBS="-lwebp -lwebpdemux"
       AC_SUBST(WEBP_LIBS)
    fi
    if test $HAVE_WEBP = yes; then
diff --git a/src/image.c b/src/image.c
index 519eafb904..f175be8923 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9053,6 +9053,7 @@ gif_load (struct frame *f, struct image *img)
  ***********************************************************************/
 
 #include "webp/decode.h"
+#include "webp/demux.h"
 
 /* Indices of image specification fields in webp_format, below.  */
 
@@ -9224,19 +9225,61 @@ webp_load (struct frame *f, struct image *img)
       goto webp_error1;
     }
 
-  /* Decode WebP data.  */
-  uint8_t *decoded;
-  int width, height;
-  if (features.has_alpha)
-    /* Linear [r0, g0, b0, a0, r1, g1, b1, a1, ...] order.  */
-    decoded = WebPDecodeRGBA (contents, size, &width, &height);
+  uint8_t *decoded = NULL;
+  int width, height, x_offset = 0, y_offset = 0, fwidth, fheight;
+
+  if (features.has_animation)
+    {
+      /* Animated image.  */
+      WebPData webp_data;
+      webp_data.bytes = WebPMalloc (size);
+      webp_data.size = size;
+      memcpy ((void*) webp_data.bytes, contents, size);
+      
+      WebPDemuxer* demux = WebPDemux(&webp_data);
+      width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
+      height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
+
+      WebPIterator iter;
+      if (WebPDemuxGetFrame (demux, 1, &iter)) {
+	do {
+	  fprintf(stderr, "Complete is %d %d\n", iter.complete, iter.has_alpha);
+	  /* Decode WebP data.  */
+	  if (iter.has_alpha)
+	    /* Linear [r0, g0, b0, a0, r1, g1, b1, a1, ...] order.  */
+	    decoded = WebPDecodeRGBA (iter.fragment.bytes, iter.fragment.size,
+				      &fwidth, &fheight);
+	  else
+	    /* Linear [r0, g0, b0, r1, g1, b1, ...] order.  */
+	    decoded = WebPDecodeRGB (iter.fragment.bytes, iter.fragment.size,
+				     &fwidth, &fheight);
+	  x_offset = iter.x_offset;
+	  y_offset = iter.y_offset;
+	  fwidth = iter.width;
+	  fheight = iter.height;
+	  break;
+	} while (WebPDemuxNextFrame (&iter));
+	WebPDemuxReleaseIterator (&iter);
+      }
+      WebPDataClear (&webp_data);
+      WebPDemuxDelete (demux);
+    }
   else
-    /* Linear [r0, g0, b0, r1, g1, b1, ...] order.  */
-    decoded = WebPDecodeRGB (contents, size, &width, &height);
+    {
+      /* Non-animated image.  */
+      if (features.has_alpha)
+	/* Linear [r0, g0, b0, a0, r1, g1, b1, a1, ...] order.  */
+	decoded = WebPDecodeRGBA (contents, size, &width, &height);
+      else
+	/* Linear [r0, g0, b0, r1, g1, b1, ...] order.  */
+	decoded = WebPDecodeRGB (contents, size, &width, &height);
+      fwidth = width;
+      fheight = height;
+    }
 
   if (!decoded)
     {
-      image_error ("Error when interpreting WebP image data");
+      image_error ("Error when decoding WebP image data");
       goto webp_error1;
     }
 
@@ -9266,9 +9309,11 @@ webp_load (struct frame *f, struct image *img)
   init_color_table ();
 
   uint8_t *p = decoded;
-  for (int y = 0; y < height; ++y)
+  fprintf(stderr, "Data: %d %d %d %d %d %d\n", width, height, fwidth, fheight,
+	  x_offset, y_offset);
+  for (int y = y_offset; y < fheight; ++y)
     {
-      for (int x = 0; x < width; ++x)
+      for (int x = x_offset; x < fwidth; ++x)
 	{
 	  int r = *p++ << 8;
 	  int g = *p++ << 8;

This bug report was last modified 3 years and 43 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.