From 21a6664cf8f54c6a8395c40a3eec9f7fdb796f55 Mon Sep 17 00:00:00 2001 From: Matin Aniss <76515905+MatinAniss@users.noreply.github.com> Date: Sat, 7 Dec 2024 09:53:27 +1100 Subject: [PATCH] gpui: Support animated WebP image (#20778) Add support for decoding animated WebP images into their individual frames. Release Notes: - N/A --- crates/gpui/src/elements/img.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/crates/gpui/src/elements/img.rs b/crates/gpui/src/elements/img.rs index 895904c8012cb8..3a1b1d92fb449b 100644 --- a/crates/gpui/src/elements/img.rs +++ b/crates/gpui/src/elements/img.rs @@ -8,7 +8,8 @@ use anyhow::{anyhow, Result}; use futures::{AsyncReadExt, Future}; use image::{ - codecs::gif::GifDecoder, AnimationDecoder, Frame, ImageBuffer, ImageError, ImageFormat, + codecs::{gif::GifDecoder, webp::WebPDecoder}, + AnimationDecoder, DynamicImage, Frame, ImageBuffer, ImageError, ImageFormat, Rgba, }; use smallvec::SmallVec; use std::{ @@ -542,6 +543,34 @@ impl Asset for ImageAssetLoader { frames } + ImageFormat::WebP => { + let mut decoder = WebPDecoder::new(Cursor::new(&bytes))?; + + if decoder.has_animation() { + let _ = decoder.set_background_color(Rgba([0, 0, 0, 0])); + let mut frames = SmallVec::new(); + + for frame in decoder.into_frames() { + let mut frame = frame?; + // Convert from RGBA to BGRA. + for pixel in frame.buffer_mut().chunks_exact_mut(4) { + pixel.swap(0, 2); + } + frames.push(frame); + } + + frames + } else { + let mut data = DynamicImage::from_decoder(decoder)?.into_rgba8(); + + // Convert from RGBA to BGRA. + for pixel in data.chunks_exact_mut(4) { + pixel.swap(0, 2); + } + + SmallVec::from_elem(Frame::new(data), 1) + } + } _ => { let mut data = image::load_from_memory_with_format(&bytes, format)?.into_rgba8();