LibGfx: Only include frames with fcTL chunks in the animation
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

Before this change, IDAT data was mistakenly always included in the
animation. Now we only include frames with explicit fcTL chunks.

As per the PNG spec (third edition):
"The static image may be included as the first frame of the animation
by the presence of a single fcTL chunk before IDAT. Otherwise, the
static image is not part of the animation."

We also fall back to the IDAT data when APNG has acTL but no fcTL
chunks. Test image is 062.png from fDAT-inherits-cICP.html from WPT.
This commit is contained in:
aplefull 2025-04-30 14:57:35 +02:00 committed by Jelle Raaijmakers
commit 71a4e18bf8
Notes: github-actions[bot] 2025-05-01 08:31:00 +00:00
4 changed files with 33 additions and 7 deletions

View file

@ -363,6 +363,22 @@ TEST_CASE(test_png)
TRY_OR_FAIL(expect_single_frame(*plugin_decoder));
}
TEST_CASE(test_apng)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("png/apng-1-frame.png"sv)));
EXPECT(Gfx::PNGImageDecoderPlugin::sniff(file->bytes()));
auto plugin_decoder = TRY_OR_FAIL(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
EXPECT_EQ(plugin_decoder->loop_count(), 0u);
auto frame = TRY_OR_FAIL(plugin_decoder->frame(0));
EXPECT_EQ(frame.duration, 1000);
EXPECT_EQ(frame.image->get_pixel(64, 32), Gfx::Color(117, 252, 76));
EXPECT_EQ(frame.image->size(), Gfx::IntSize(128, 64));
}
TEST_CASE(test_exif)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("png/exif.png"sv)));