1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:07:45 +00:00

LibGfx: Implement WebPImageDecoderPlugin::loop_count()

Turns out extended-lossless-animated.webp did have a loop count of 0.
So I opened it in Hex Fiend and changed the byte at position 42
(which is the first byte of the little-endian u16 storing the loop
count) to 0x2A, so that the test can compare the loop count to something
not 0.
This commit is contained in:
Nico Weber 2023-02-26 09:13:27 -05:00 committed by Linus Groh
parent 3c5450b8be
commit fa34832297
3 changed files with 33 additions and 5 deletions

View file

@ -79,6 +79,11 @@ struct VP8XHeader {
u32 height;
};
struct ANIMChunk {
u32 background_color;
u16 loop_count;
};
}
struct WebPLoadingContext {
@ -333,6 +338,20 @@ static ErrorOr<VP8XHeader> decode_webp_chunk_VP8X(WebPLoadingContext& context, C
return VP8XHeader { has_icc, has_alpha, has_exif, has_xmp, has_animation, width, height };
}
// https://developers.google.com/speed/webp/docs/riff_container#animation
static ErrorOr<ANIMChunk> decode_webp_chunk_ANIM(WebPLoadingContext& context, Chunk const& anim_chunk)
{
VERIFY(anim_chunk.type == FourCC("ANIM"));
if (anim_chunk.data.size() < 6)
return context.error("WebPImageDecoderPlugin: ANIM chunk too small");
u8 const* data = anim_chunk.data.data();
u32 background_color = (u32)data[0] | ((u32)data[1] << 8) | ((u32)data[2] << 16) | ((u32)data[3] << 24);
u16 loop_count = data[4] | (data[5] << 8);
return ANIMChunk { background_color, loop_count };
}
// https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
static ErrorOr<void> decode_webp_extended(WebPLoadingContext& context, ReadonlyBytes chunks)
{
@ -532,8 +551,19 @@ bool WebPImageDecoderPlugin::is_animated()
size_t WebPImageDecoderPlugin::loop_count()
{
// FIXME
return 0;
if (!is_animated())
return 0;
if (m_context->state < WebPLoadingContext::State::ChunksDecoded) {
if (decode_webp_chunks(*m_context).is_error())
return 0;
}
auto anim_or_error = decode_webp_chunk_ANIM(*m_context, m_context->animation_header_chunk.value());
if (decode_webp_chunks(*m_context).is_error())
return 0;
return anim_or_error.value().loop_count;
}
size_t WebPImageDecoderPlugin::frame_count()