mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-12 22:22:55 +00:00
WebP lossless files that use a color indexing transform with <= 16 colors use pixel bundling to pack 2, 4, or 8 pixels into a single pixel. If the image's width doesn't happen to be an exact multiple of the bundling factor, we need to: 1. Use ceil_div() instead of just dividing the width by the bundling factor 2. Remember the original width and use it instead of computing reduced width times bundling factor This does these changes, and adds a simple test for it -- it at least checks that the decoded images have the right size. (I created these images myself in Photoshop, and used the same technique as for Tests/LibGfx/test-inputs/catdog-alert-*.webp to create images with a certain number of colors.)
456 lines
17 KiB
C++
456 lines
17 KiB
C++
/*
|
|
* Copyright (c) 2021, the SerenityOS developers.
|
|
* Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/DeprecatedString.h>
|
|
#include <LibCore/MappedFile.h>
|
|
#include <LibGfx/ImageFormats/BMPLoader.h>
|
|
#include <LibGfx/ImageFormats/GIFLoader.h>
|
|
#include <LibGfx/ImageFormats/ICOLoader.h>
|
|
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
|
#include <LibGfx/ImageFormats/JPEGLoader.h>
|
|
#include <LibGfx/ImageFormats/PBMLoader.h>
|
|
#include <LibGfx/ImageFormats/PGMLoader.h>
|
|
#include <LibGfx/ImageFormats/PNGLoader.h>
|
|
#include <LibGfx/ImageFormats/PPMLoader.h>
|
|
#include <LibGfx/ImageFormats/TGALoader.h>
|
|
#include <LibGfx/ImageFormats/WebPLoader.h>
|
|
#include <LibTest/TestCase.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifdef AK_OS_SERENITY
|
|
# define TEST_INPUT(x) ("/usr/Tests/LibGfx/test-inputs/" x)
|
|
#else
|
|
# define TEST_INPUT(x) ("test-inputs/" x)
|
|
#endif
|
|
|
|
TEST_CASE(test_bmp)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgba32-1.bmp"sv)));
|
|
EXPECT(Gfx::BMPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::BMPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_gif)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("download-animation.gif"sv)));
|
|
EXPECT(Gfx::GIFImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::GIFImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(1));
|
|
EXPECT(frame.duration == 400);
|
|
}
|
|
|
|
TEST_CASE(test_not_ico)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie.png"sv)));
|
|
EXPECT(!Gfx::ICOImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::ICOImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(!plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT(plugin_decoder->frame(0).is_error());
|
|
}
|
|
|
|
TEST_CASE(test_bmp_embedded_in_ico)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("serenity.ico"sv)));
|
|
EXPECT(Gfx::ICOImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::ICOImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT(!plugin_decoder->frame(0).is_error());
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_sof0_one_scan)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgb24.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_sof0_several_scans)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("several_scans.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_rgb_components)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("rgb_components.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_sof2_spectral_selection)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("spectral_selection.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800));
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_sof0_several_scans_odd_number_mcu)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("several_scans_odd_number_mcu.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(600, 600));
|
|
}
|
|
|
|
TEST_CASE(test_jpeg_sof2_successive_aproximation)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("successive_approximation.jpg"sv)));
|
|
EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(600, 800));
|
|
}
|
|
|
|
TEST_CASE(test_pbm)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.pbm"sv)));
|
|
EXPECT(Gfx::PBMImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::PBMImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_pgm)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.pgm"sv)));
|
|
EXPECT(Gfx::PGMImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::PGMImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_png)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie.png"sv)));
|
|
EXPECT(Gfx::PNGImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::PNGImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_ppm)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.ppm"sv)));
|
|
EXPECT(Gfx::PPMImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::PPMImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT(plugin_decoder->frame_count());
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_targa_bottom_left)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-bottom-left-uncompressed.tga"sv)));
|
|
EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
|
|
auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_targa_top_left)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-top-left-uncompressed.tga"sv)));
|
|
EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
|
|
auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_targa_bottom_left_compressed)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-bottom-left-compressed.tga"sv)));
|
|
EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
|
|
auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_targa_top_left_compressed)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-top-left-compressed.tga"sv)));
|
|
EXPECT(MUST(Gfx::TGAImageDecoderPlugin::validate_before_create(file->bytes())));
|
|
auto plugin_decoder = MUST(Gfx::TGAImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT(frame.duration == 0);
|
|
}
|
|
|
|
TEST_CASE(test_webp_simple_lossy)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("simple-vp8.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(240, 240));
|
|
}
|
|
|
|
TEST_CASE(test_webp_simple_lossless)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("simple-vp8l.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(386, 395));
|
|
|
|
// Ironically, simple-vp8l.webp is a much more complex file than extended-lossless.webp tested below.
|
|
// extended-lossless.webp tests the decoding basics.
|
|
// This here tests the predictor, color, and subtract green transforms,
|
|
// as well as meta prefix images, one-element canonical code handling,
|
|
// and handling of canonical codes with more than 288 elements.
|
|
// This image uses all 13 predictor modes of the predictor transform.
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(386, 395));
|
|
|
|
// This pixel tests all predictor modes except 5, 7, 8, 9, and 13.
|
|
EXPECT_EQ(frame.image->get_pixel(289, 332), Gfx::Color(0xf2, 0xee, 0xd3, 255));
|
|
}
|
|
|
|
TEST_CASE(test_webp_extended_lossy)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossy.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(417, 223));
|
|
}
|
|
|
|
TEST_CASE(test_webp_extended_lossless)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(417, 223));
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(417, 223));
|
|
|
|
// Check some basic pixels.
|
|
EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color(0, 0, 0, 0));
|
|
EXPECT_EQ(frame.image->get_pixel(43, 75), Gfx::Color(255, 0, 0, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(141, 75), Gfx::Color(0, 255, 0, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(235, 75), Gfx::Color(0, 0, 255, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(341, 75), Gfx::Color(0, 0, 0, 128));
|
|
|
|
// Check pixels using the color cache.
|
|
EXPECT_EQ(frame.image->get_pixel(94, 73), Gfx::Color(255, 0, 0, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(176, 115), Gfx::Color(0, 255, 0, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(290, 89), Gfx::Color(0, 0, 255, 255));
|
|
EXPECT_EQ(frame.image->get_pixel(359, 73), Gfx::Color(0, 0, 0, 128));
|
|
}
|
|
|
|
TEST_CASE(test_webp_simple_lossless_color_index_transform)
|
|
{
|
|
// In addition to testing the index transform, this file also tests handling of explicity setting max_symbol.
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("Qpalette.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT(!plugin_decoder->is_animated());
|
|
EXPECT(!plugin_decoder->loop_count());
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(256, 256));
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(256, 256));
|
|
|
|
EXPECT_EQ(frame.image->get_pixel(100, 100), Gfx::Color(0x73, 0x37, 0x23, 0xff));
|
|
}
|
|
|
|
TEST_CASE(test_webp_simple_lossless_color_index_transform_pixel_bundling)
|
|
{
|
|
struct TestCase {
|
|
StringView file_name;
|
|
Gfx::Color line_color;
|
|
Gfx::Color background_color;
|
|
};
|
|
|
|
// The number after the dash is the number of colors in each file's color index bitmap.
|
|
// catdog-alert-2 tests the 1-bit-per-pixel case,
|
|
// catdog-alert-3 tests the 2-bit-per-pixel case,
|
|
// catdog-alert-8 and catdog-alert-13 both test the 4-bits-per-pixel case.
|
|
TestCase test_cases[] = {
|
|
{ "catdog-alert-2.webp"sv, Gfx::Color(0x35, 0x12, 0x0a, 0xff), Gfx::Color(0xf3, 0xe6, 0xd8, 0xff) },
|
|
{ "catdog-alert-3.webp"sv, Gfx::Color(0x35, 0x12, 0x0a, 0xff), Gfx::Color(0, 0, 0, 0) },
|
|
{ "catdog-alert-8.webp"sv, Gfx::Color(0, 0, 0, 255), Gfx::Color(0, 0, 0, 0) },
|
|
{ "catdog-alert-13.webp"sv, Gfx::Color(0, 0, 0, 255), Gfx::Color(0, 0, 0, 0) },
|
|
};
|
|
|
|
for (auto test_case : test_cases) {
|
|
auto file = MUST(Core::MappedFile::map(MUST(String::formatted("{}{}", TEST_INPUT(""), test_case.file_name))));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(32, 32));
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(32, 32));
|
|
|
|
EXPECT_EQ(frame.image->get_pixel(4, 0), test_case.background_color);
|
|
EXPECT_EQ(frame.image->get_pixel(5, 0), test_case.line_color);
|
|
|
|
EXPECT_EQ(frame.image->get_pixel(9, 5), test_case.background_color);
|
|
EXPECT_EQ(frame.image->get_pixel(10, 5), test_case.line_color);
|
|
EXPECT_EQ(frame.image->get_pixel(11, 5), test_case.background_color);
|
|
}
|
|
}
|
|
|
|
TEST_CASE(test_webp_simple_lossless_color_index_transform_pixel_bundling_odd_width)
|
|
{
|
|
StringView file_names[] = {
|
|
"width11-height11-colors2.webp"sv,
|
|
"width11-height11-colors3.webp"sv,
|
|
"width11-height11-colors15.webp"sv,
|
|
};
|
|
|
|
for (auto file_name : file_names) {
|
|
auto file = MUST(Core::MappedFile::map(MUST(String::formatted("{}{}", TEST_INPUT(""), file_name))));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 1u);
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(11, 11));
|
|
|
|
auto frame = MUST(plugin_decoder->frame(0));
|
|
EXPECT_EQ(frame.image->size(), Gfx::IntSize(11, 11));
|
|
}
|
|
}
|
|
|
|
TEST_CASE(test_webp_extended_lossless_animated)
|
|
{
|
|
auto file = MUST(Core::MappedFile::map(TEST_INPUT("extended-lossless-animated.webp"sv)));
|
|
EXPECT(Gfx::WebPImageDecoderPlugin::sniff(file->bytes()));
|
|
auto plugin_decoder = MUST(Gfx::WebPImageDecoderPlugin::create(file->bytes()));
|
|
EXPECT(plugin_decoder->initialize());
|
|
|
|
EXPECT_EQ(plugin_decoder->frame_count(), 8u);
|
|
EXPECT(plugin_decoder->is_animated());
|
|
EXPECT_EQ(plugin_decoder->loop_count(), 42u);
|
|
|
|
EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(990, 1050));
|
|
}
|