diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index 911f675899..5cfb65fff2 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -1395,7 +1395,7 @@ TEST_CASE(test_webp_extended_lossless_animated) EXPECT_EQ(frame.image->get_pixel(500, 700), Gfx::Color::Yellow); // This one isn't the same in all frames. - EXPECT_EQ(frame.image->get_pixel(500, 0), (frame_index == 2 || frame_index == 6) ? Gfx::Color::Black : Gfx::Color(255, 255, 255, 0)); + EXPECT_EQ(frame.image->get_pixel(500, 0), (frame_index == 2 || frame_index == 6) ? Gfx::Color::Black : Gfx::Color(0, 0, 0, 0)); } } diff --git a/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp index a2b45591a5..5c31975994 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp @@ -538,7 +538,7 @@ static ErrorOr> decode_webp_image_data(WebPLoadingContext& return bitmap; } -// https://developers.google.com/speed/webp/docs/riff_container#assembling_the_canvas_from_frames +// https://developers.google.com/speed/webp/docs/riff_container#canvas_assembly_from_frames static ErrorOr decode_webp_animation_frame(WebPLoadingContext& context, size_t frame_index) { if (frame_index >= context.animation_frame_chunks_data->size()) @@ -547,7 +547,15 @@ static ErrorOr decode_webp_animation_frame(WebPLoadingCont VERIFY(context.first_chunk->id() == "VP8X"sv); VERIFY(context.vp8x_header.has_animation); - Color clear_color = Color::from_argb(context.animation_header_chunk_data->background_color); + // The spec says + // "canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with + // background color ANIM.background_color." + // But: + // * libwebp always fills with transparent black (#00000000) + // * some images (e.g. images written by Aseprite) set the background color to fully opaque white + // These images then end up with a nice transparent background in libwebp-based decoders (i.e. basically everywhere) + // but show a silly opaque border in ours. So don't use context.animation_header_chunk_data->background_color here. + Color clear_color(Color::Transparent); size_t start_frame = context.current_frame + 1; dbgln_if(WEBP_DEBUG, "start_frame {} context.current_frame {}", start_frame, context.current_frame); @@ -555,7 +563,8 @@ static ErrorOr decode_webp_animation_frame(WebPLoadingCont start_frame = 0; auto format = context.vp8x_header.has_alpha ? BitmapFormat::BGRA8888 : BitmapFormat::BGRx8888; context.bitmap = TRY(Bitmap::create(format, { context.vp8x_header.width, context.vp8x_header.height })); - context.bitmap->fill(clear_color); + if (clear_color != Color(Color::Transparent)) // Bitmaps start out transparent, so only fill if not transparent. + context.bitmap->fill(clear_color); } else if (frame_index < context.current_frame) { start_frame = 0; }