LibGfx+Tests: Add test for webp ICC loading and fix bug
I drew the two webp files in Photoshop and saved them using the "Save a Copy..." dialog, with ICC profile and all other boxes checked. (I also tried saving with all the boxes unchecked, but it still wrote an extended webp instead of a basic file.) The lossless file exposed a bug: I didn't handle chunk padding correctly before this patch.
This commit is contained in:
parent
7485521619
commit
14c0bae704
Notes:
sideshowbarker
2024-07-17 03:45:48 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/14c0bae704 Pull-request: https://github.com/SerenityOS/serenity/pull/17602
4 changed files with 45 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
#include <LibGfx/ICC/Profile.h>
|
||||
#include <LibGfx/JPEGLoader.h>
|
||||
#include <LibGfx/PNGLoader.h>
|
||||
#include <LibGfx/WebPLoader.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
#ifdef AK_OS_SERENITY
|
||||
|
@ -41,6 +42,30 @@ TEST_CASE(jpg)
|
|||
EXPECT(icc_profile->is_v4());
|
||||
}
|
||||
|
||||
TEST_CASE(webp_extended_lossless)
|
||||
{
|
||||
auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless.webp"sv)));
|
||||
auto webp = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
||||
EXPECT(webp->initialize());
|
||||
auto icc_bytes = MUST(webp->icc_data());
|
||||
EXPECT(icc_bytes.has_value());
|
||||
|
||||
auto icc_profile = MUST(Gfx::ICC::Profile::try_load_from_externally_owned_memory(icc_bytes.value()));
|
||||
EXPECT(icc_profile->is_v2());
|
||||
}
|
||||
|
||||
TEST_CASE(webp_extended_lossy)
|
||||
{
|
||||
auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossy.webp"sv)));
|
||||
auto webp = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
||||
EXPECT(webp->initialize());
|
||||
auto icc_bytes = MUST(webp->icc_data());
|
||||
EXPECT(icc_bytes.has_value());
|
||||
|
||||
auto icc_profile = MUST(Gfx::ICC::Profile::try_load_from_externally_owned_memory(icc_bytes.value()));
|
||||
EXPECT(icc_profile->is_v2());
|
||||
}
|
||||
|
||||
TEST_CASE(serialize_icc)
|
||||
{
|
||||
auto file = MUST(Core::MappedFile::map(TEST_INPUT("p3-v4.icc"sv)));
|
||||
|
|
BIN
Tests/LibGfx/test-inputs/extended-lossless.webp
Normal file
BIN
Tests/LibGfx/test-inputs/extended-lossless.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
BIN
Tests/LibGfx/test-inputs/extended-lossy.webp
Normal file
BIN
Tests/LibGfx/test-inputs/extended-lossy.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
|
@ -110,6 +110,7 @@ static ErrorOr<void> decode_webp_header(WebPLoadingContext& context)
|
|||
return {};
|
||||
}
|
||||
|
||||
// https://developers.google.com/speed/webp/docs/riff_container#riff_file_format
|
||||
static ErrorOr<Chunk> decode_webp_chunk_header(WebPLoadingContext& context, ReadonlyBytes chunks)
|
||||
{
|
||||
if (chunks.size() < sizeof(ChunkHeader)) {
|
||||
|
@ -128,10 +129,29 @@ static ErrorOr<Chunk> decode_webp_chunk_header(WebPLoadingContext& context, Read
|
|||
return Chunk { header.chunk_type, { chunks.data() + sizeof(ChunkHeader), header.chunk_size } };
|
||||
}
|
||||
|
||||
// https://developers.google.com/speed/webp/docs/riff_container#riff_file_format
|
||||
static ErrorOr<Chunk> decode_webp_advance_chunk(WebPLoadingContext& context, ReadonlyBytes& chunks)
|
||||
{
|
||||
auto chunk = TRY(decode_webp_chunk_header(context, chunks));
|
||||
|
||||
// "Chunk Size: 32 bits (uint32)
|
||||
// The size of the chunk in bytes, not including this field, the chunk identifier or padding.
|
||||
// Chunk Payload: Chunk Size bytes
|
||||
// The data payload. If Chunk Size is odd, a single padding byte -- that MUST be 0 to conform with RIFF -- is added."
|
||||
chunks = chunks.slice(sizeof(ChunkHeader) + chunk.data.size());
|
||||
|
||||
if (chunk.data.size() % 2 != 0) {
|
||||
if (chunks.is_empty()) {
|
||||
context.state = WebPLoadingContext::State::Error;
|
||||
return Error::from_string_literal("Missing data for padding byte");
|
||||
}
|
||||
if (*chunks.data() != 0) {
|
||||
context.state = WebPLoadingContext::State::Error;
|
||||
return Error::from_string_literal("Padding byte is not 0");
|
||||
}
|
||||
chunks = chunks.slice(1);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue