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;