mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-13 13:02:28 +00:00
LibGfx/AnimationWriter: Survive animations with two identical frames
Creating a completely empty bitmap fails. Just write a 1x1 bitmap if the bitmap ends up empty for now.
This commit is contained in:
parent
51617929dc
commit
b7b51d01c3
Notes:
sideshowbarker
2024-07-17 03:51:15 +09:00
Author: https://github.com/nico
Commit: b7b51d01c3
Pull-request: https://github.com/SerenityOS/serenity/pull/24410
2 changed files with 38 additions and 0 deletions
|
@ -229,3 +229,34 @@ TEST_CASE(test_webp_incremental_animation)
|
||||||
EXPECT_EQ(frame1.duration, 200);
|
EXPECT_EQ(frame1.duration, 200);
|
||||||
expect_bitmaps_equal(*frame1.image, *rgb_bitmap_2);
|
expect_bitmaps_equal(*frame1.image, *rgb_bitmap_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_webp_incremental_animation_two_identical_frames)
|
||||||
|
{
|
||||||
|
auto rgb_bitmap = TRY_OR_FAIL(create_test_rgba_bitmap());
|
||||||
|
rgb_bitmap = TRY_OR_FAIL(rgb_bitmap->cropped({ 0, 0, 40, 20 })); // Even-sized.
|
||||||
|
|
||||||
|
// 20 kiB is enough for two 47x33 frames.
|
||||||
|
auto stream_buffer = TRY_OR_FAIL(ByteBuffer::create_uninitialized(20 * 1024));
|
||||||
|
FixedMemoryStream stream { Bytes { stream_buffer } };
|
||||||
|
|
||||||
|
auto animation_writer = TRY_OR_FAIL(Gfx::WebPWriter::start_encoding_animation(stream, rgb_bitmap->size()));
|
||||||
|
|
||||||
|
TRY_OR_FAIL(animation_writer->add_frame(*rgb_bitmap, 100));
|
||||||
|
TRY_OR_FAIL(animation_writer->add_frame_relative_to_last_frame(*rgb_bitmap, 200, *rgb_bitmap));
|
||||||
|
|
||||||
|
auto encoded_animation = ReadonlyBytes { stream_buffer.data(), stream.offset() };
|
||||||
|
|
||||||
|
auto decoded_animation_plugin = TRY_OR_FAIL(Gfx::WebPImageDecoderPlugin::create(encoded_animation));
|
||||||
|
EXPECT(decoded_animation_plugin->is_animated());
|
||||||
|
EXPECT_EQ(decoded_animation_plugin->frame_count(), 2u);
|
||||||
|
EXPECT_EQ(decoded_animation_plugin->loop_count(), 0u);
|
||||||
|
EXPECT_EQ(decoded_animation_plugin->size(), rgb_bitmap->size());
|
||||||
|
|
||||||
|
auto frame0 = TRY_OR_FAIL(decoded_animation_plugin->frame(0));
|
||||||
|
EXPECT_EQ(frame0.duration, 100);
|
||||||
|
expect_bitmaps_equal(*frame0.image, *rgb_bitmap);
|
||||||
|
|
||||||
|
auto frame1 = TRY_OR_FAIL(decoded_animation_plugin->frame(1));
|
||||||
|
EXPECT_EQ(frame1.duration, 200);
|
||||||
|
expect_bitmaps_equal(*frame1.image, *rgb_bitmap);
|
||||||
|
}
|
||||||
|
|
|
@ -80,6 +80,13 @@ ErrorOr<void> AnimationWriter::add_frame_relative_to_last_frame(Bitmap& frame, i
|
||||||
|
|
||||||
auto rect = rect_where_pixels_are_different(*last_frame, frame);
|
auto rect = rect_where_pixels_are_different(*last_frame, frame);
|
||||||
|
|
||||||
|
if (rect.is_empty()) {
|
||||||
|
// The frame is identical to the last frame. Don't store an empty bitmap.
|
||||||
|
// FIXME: We could delay writing the last frame until we know that the next frame is different,
|
||||||
|
// and just keep increasing that frame's duration instead.
|
||||||
|
rect = { 0, 0, 1, 1 };
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: It would be nice to have a way to crop a bitmap without copying the data.
|
// FIXME: It would be nice to have a way to crop a bitmap without copying the data.
|
||||||
auto differences = TRY(frame.cropped(rect));
|
auto differences = TRY(frame.cropped(rect));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue