|
6 | 6 |
|
7 | 7 | #include <AK/MemoryStream.h>
|
8 | 8 | #include <LibGfx/Bitmap.h>
|
| 9 | +#include <LibGfx/ICC/BinaryWriter.h> |
| 10 | +#include <LibGfx/ICC/Profile.h> |
| 11 | +#include <LibGfx/ICC/WellKnownProfiles.h> |
9 | 12 | #include <LibGfx/ImageFormats/BMPLoader.h>
|
10 | 13 | #include <LibGfx/ImageFormats/BMPWriter.h>
|
11 | 14 | #include <LibGfx/ImageFormats/JPEGLoader.h>
|
@@ -37,31 +40,38 @@ static ErrorOr<NonnullRefPtr<Gfx::Bitmap>> expect_single_frame_of_size(Gfx::Imag
|
37 | 40 | return frame;
|
38 | 41 | }
|
39 | 42 |
|
40 |
| -template<class Writer, class Loader> |
41 |
| -static ErrorOr<NonnullRefPtr<Gfx::Bitmap>> get_roundtrip_bitmap(Gfx::Bitmap const& bitmap) |
| 43 | +template<class Writer, class... ExtraArgs> |
| 44 | +static ErrorOr<ByteBuffer> encode_bitmap(Gfx::Bitmap const& bitmap, ExtraArgs... extra_args) |
42 | 45 | {
|
43 |
| - ByteBuffer encoded_data; |
44 |
| - if constexpr (requires(AllocatingMemoryStream stream) { Writer::encode(stream, bitmap); }) { |
| 46 | + if constexpr (requires(AllocatingMemoryStream stream) { Writer::encode(stream, bitmap, extra_args...); }) { |
45 | 47 | AllocatingMemoryStream stream;
|
46 |
| - TRY(Writer::encode(stream, bitmap)); |
47 |
| - encoded_data = TRY(stream.read_until_eof()); |
| 48 | + TRY(Writer::encode(stream, bitmap, extra_args...)); |
| 49 | + return stream.read_until_eof(); |
48 | 50 | } else {
|
49 |
| - encoded_data = TRY(Writer::encode(bitmap)); |
| 51 | + return Writer::encode(bitmap, extra_args...); |
50 | 52 | }
|
| 53 | +} |
| 54 | + |
| 55 | +template<class Writer, class Loader> |
| 56 | +static ErrorOr<NonnullRefPtr<Gfx::Bitmap>> get_roundtrip_bitmap(Gfx::Bitmap const& bitmap) |
| 57 | +{ |
| 58 | + auto encoded_data = TRY(encode_bitmap<Writer>(bitmap)); |
| 59 | + return expect_single_frame_of_size(*TRY(Loader::create(encoded_data)), bitmap.size()); |
| 60 | +} |
51 | 61 |
|
52 |
| - auto plugin = TRY(Loader::create(encoded_data)); |
53 |
| - return expect_single_frame_of_size(*plugin, bitmap.size()); |
| 62 | +static void expect_bitmaps_equal(Gfx::Bitmap const& a, Gfx::Bitmap const& b) |
| 63 | +{ |
| 64 | + VERIFY(a.size() == b.size()); |
| 65 | + for (int y = 0; y < a.height(); ++y) |
| 66 | + for (int x = 0; x < a.width(); ++x) |
| 67 | + EXPECT_EQ(a.get_pixel(x, y), b.get_pixel(x, y)); |
54 | 68 | }
|
55 | 69 |
|
56 | 70 | template<class Writer, class Loader>
|
57 | 71 | static ErrorOr<void> test_roundtrip(Gfx::Bitmap const& bitmap)
|
58 | 72 | {
|
59 | 73 | auto decoded = TRY((get_roundtrip_bitmap<Writer, Loader>(bitmap)));
|
60 |
| - |
61 |
| - for (int y = 0; y < bitmap.height(); ++y) |
62 |
| - for (int x = 0; x < bitmap.width(); ++x) |
63 |
| - EXPECT_EQ(decoded->get_pixel(x, y), bitmap.get_pixel(x, y)); |
64 |
| - |
| 74 | + expect_bitmaps_equal(*decoded, bitmap); |
65 | 75 | return {};
|
66 | 76 | }
|
67 | 77 |
|
@@ -120,3 +130,18 @@ TEST_CASE(test_webp)
|
120 | 130 | TRY_OR_FAIL((test_roundtrip<Gfx::WebPWriter, Gfx::WebPImageDecoderPlugin>(TRY_OR_FAIL(create_test_rgb_bitmap()))));
|
121 | 131 | TRY_OR_FAIL((test_roundtrip<Gfx::WebPWriter, Gfx::WebPImageDecoderPlugin>(TRY_OR_FAIL(create_test_rgba_bitmap()))));
|
122 | 132 | }
|
| 133 | + |
| 134 | +TEST_CASE(test_webp_icc) |
| 135 | +{ |
| 136 | + auto sRGB_icc_profile = MUST(Gfx::ICC::sRGB()); |
| 137 | + auto sRGB_icc_data = MUST(Gfx::ICC::encode(sRGB_icc_profile)); |
| 138 | + |
| 139 | + auto rgba_bitmap = TRY_OR_FAIL(create_test_rgba_bitmap()); |
| 140 | + auto encoded_rgba_bitmap = TRY_OR_FAIL((encode_bitmap<Gfx::WebPWriter>(rgba_bitmap, Gfx::WebPEncoderOptions { .icc_data = sRGB_icc_data }))); |
| 141 | + |
| 142 | + auto decoded_rgba_plugin = TRY_OR_FAIL(Gfx::WebPImageDecoderPlugin::create(encoded_rgba_bitmap)); |
| 143 | + expect_bitmaps_equal(*TRY_OR_FAIL(expect_single_frame_of_size(*decoded_rgba_plugin, rgba_bitmap->size())), rgba_bitmap); |
| 144 | + auto decoded_rgba_profile = TRY_OR_FAIL(Gfx::ICC::Profile::try_load_from_externally_owned_memory(TRY_OR_FAIL(decoded_rgba_plugin->icc_data()).value())); |
| 145 | + auto reencoded_icc_data = TRY_OR_FAIL(Gfx::ICC::encode(decoded_rgba_profile)); |
| 146 | + EXPECT_EQ(sRGB_icc_data, reencoded_icc_data); |
| 147 | +} |
0 commit comments