From 578a3af87d6d4f4fc1e4baebc3b4aea689b4f8ff Mon Sep 17 00:00:00 2001 From: InvalidUsernameException Date: Sat, 19 Apr 2025 17:26:56 +0200 Subject: [PATCH] LibGfx: Support missing pixel formats in get_pixel() Bitmap::get_pixel() was only handling two out of the four possible pixel formats, asserting when called with the other two. The asserting code path was triggered when loading JPEG XL images, causing crashes on pages like https://jpegxl.info/resources/jpeg-xl-test-page or https://html5test.co/. --- Libraries/LibGfx/Bitmap.h | 16 ++++++ Libraries/LibGfx/Color.h | 6 +++ Tests/LibGfx/TestColor.cpp | 46 ++++++++++++++++++ .../jpegxl/3x3_srgb_lossless-ref.html | 4 ++ .../jpegxl/3x3a_srgb_lossless-ref.html | 4 ++ .../jpegxl/resources/3x3_srgb_lossless.png | Bin 0 -> 152 bytes .../jpegxl/resources/3x3a_srgb_lossless.png | Bin 0 -> 163 bytes .../wpt-import/jpegxl/3x3_srgb_lossless.html | 8 +++ .../wpt-import/jpegxl/3x3a_srgb_lossless.html | 8 +++ .../jpegxl/resources/3x3_srgb_lossless.jxl | Bin 0 -> 66 bytes .../jpegxl/resources/3x3a_srgb_lossless.jxl | Bin 0 -> 66 bytes 11 files changed, 92 insertions(+) create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3_srgb_lossless-ref.html create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3a_srgb_lossless-ref.html create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/jpegxl/resources/3x3_srgb_lossless.png create mode 100644 Tests/LibWeb/Ref/expected/wpt-import/jpegxl/resources/3x3a_srgb_lossless.png create mode 100644 Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3_srgb_lossless.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3a_srgb_lossless.html create mode 100644 Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3_srgb_lossless.jxl create mode 100644 Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3a_srgb_lossless.jxl diff --git a/Libraries/LibGfx/Bitmap.h b/Libraries/LibGfx/Bitmap.h index b987690fd5e..b5cd59a2eb2 100644 --- a/Libraries/LibGfx/Bitmap.h +++ b/Libraries/LibGfx/Bitmap.h @@ -244,6 +244,18 @@ ALWAYS_INLINE Color Bitmap::unchecked_get_pixel(int x, return Color::from_argb(unchecked_scanline(y)[x]); } +template<> +ALWAYS_INLINE Color Bitmap::unchecked_get_pixel(int x, int y) const +{ + return Color::from_bgr(unchecked_scanline(y)[x]); +} + +template<> +ALWAYS_INLINE Color Bitmap::unchecked_get_pixel(int x, int y) const +{ + return Color::from_abgr(unchecked_scanline(y)[x]); +} + template ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const { @@ -259,6 +271,10 @@ ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const return get_pixel(x, y); case StorageFormat::BGRA8888: return get_pixel(x, y); + case StorageFormat::RGBA8888: + return get_pixel(x, y); + case StorageFormat::RGBx8888: + return get_pixel(x, y); default: VERIFY_NOT_REACHED(); } diff --git a/Libraries/LibGfx/Color.h b/Libraries/LibGfx/Color.h index 6b62fb4175b..5afe6f2533c 100644 --- a/Libraries/LibGfx/Color.h +++ b/Libraries/LibGfx/Color.h @@ -95,6 +95,12 @@ public: static constexpr Color from_rgb(unsigned rgb) { return Color(rgb | 0xff000000); } static constexpr Color from_argb(unsigned argb) { return Color(argb); } + static constexpr Color from_abgr(unsigned abgr) + { + unsigned argb = (abgr & 0xff00ff00) | ((abgr & 0xff0000) >> 16) | ((abgr & 0xff) << 16); + return Color::from_argb(argb); + } + static constexpr Color from_bgr(unsigned bgr) { return Color::from_abgr(bgr | 0xff000000); } static constexpr Color from_yuv(YUV const& yuv) { return from_yuv(yuv.y, yuv.u, yuv.v); } static constexpr Color from_yuv(float y, float u, float v) diff --git a/Tests/LibGfx/TestColor.cpp b/Tests/LibGfx/TestColor.cpp index 01cdd85f099..fb8e03b66f5 100644 --- a/Tests/LibGfx/TestColor.cpp +++ b/Tests/LibGfx/TestColor.cpp @@ -15,6 +15,52 @@ TEST_CASE(color) } } +TEST_CASE(from_rgb) +{ + EXPECT_EQ(Color(0x00, 0x00, 0xff), Color::from_rgb(0x000000ff)); + EXPECT_EQ(Color(0x00, 0xff, 0x00), Color::from_rgb(0x0000ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00), Color::from_rgb(0x00ff0000)); + + EXPECT_EQ(Color(0x00, 0x00, 0xff), Color::from_rgb(0xff0000ff)); + EXPECT_EQ(Color(0x00, 0xff, 0x00), Color::from_rgb(0xff00ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00), Color::from_rgb(0xffff0000)); + + EXPECT_EQ(Color(0xaa, 0xbb, 0xcc), Color::from_rgb(0x00aabbcc)); +} + +TEST_CASE(from_argb) +{ + EXPECT_EQ(Color(0x00, 0x00, 0x00, 0xff), Color::from_argb(0xff000000)); + EXPECT_EQ(Color(0x00, 0x00, 0xff, 0x00), Color::from_argb(0x000000ff)); + EXPECT_EQ(Color(0x00, 0xff, 0x00, 0x00), Color::from_argb(0x0000ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00, 0x00), Color::from_argb(0x00ff0000)); + + EXPECT_EQ(Color(0xaa, 0xbb, 0xcc, 0xdd), Color::from_argb(0xddaabbcc)); +} + +TEST_CASE(from_bgr) +{ + EXPECT_EQ(Color(0x00, 0x00, 0xff), Color::from_bgr(0x00ff0000)); + EXPECT_EQ(Color(0x00, 0xff, 0x00), Color::from_bgr(0x0000ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00), Color::from_bgr(0x000000ff)); + + EXPECT_EQ(Color(0x00, 0x00, 0xff), Color::from_bgr(0xffff0000)); + EXPECT_EQ(Color(0x00, 0xff, 0x00), Color::from_bgr(0xff00ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00), Color::from_bgr(0xff0000ff)); + + EXPECT_EQ(Color(0xaa, 0xbb, 0xcc), Color::from_bgr(0x00ccbbaa)); +} + +TEST_CASE(from_abgr) +{ + EXPECT_EQ(Color(0x00, 0x00, 0x00, 0xff), Color::from_abgr(0xff000000)); + EXPECT_EQ(Color(0x00, 0x00, 0xff, 0x00), Color::from_abgr(0x00ff0000)); + EXPECT_EQ(Color(0x00, 0xff, 0x00, 0x00), Color::from_abgr(0x0000ff00)); + EXPECT_EQ(Color(0xff, 0x00, 0x00, 0x00), Color::from_abgr(0x000000ff)); + + EXPECT_EQ(Color(0xaa, 0xbb, 0xcc, 0xdd), Color::from_abgr(0xddccbbaa)); +} + TEST_CASE(all_green) { EXPECT_EQ(Color(Color::NamedColor::Green), Color::from_lab(87.8185, -79.2711, 80.9946)); diff --git a/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3_srgb_lossless-ref.html b/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3_srgb_lossless-ref.html new file mode 100644 index 00000000000..498cbf3944a --- /dev/null +++ b/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3_srgb_lossless-ref.html @@ -0,0 +1,4 @@ + +JPEG XL test reference + + diff --git a/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3a_srgb_lossless-ref.html b/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3a_srgb_lossless-ref.html new file mode 100644 index 00000000000..1a5ad157df9 --- /dev/null +++ b/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/3x3a_srgb_lossless-ref.html @@ -0,0 +1,4 @@ + +JPEG XL test reference + + diff --git a/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/resources/3x3_srgb_lossless.png b/Tests/LibWeb/Ref/expected/wpt-import/jpegxl/resources/3x3_srgb_lossless.png new file mode 100644 index 0000000000000000000000000000000000000000..f314145a13949d190710a92e7d1c119d0ef302f5 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0y~yU|NP6H&CINibOG4#;8q=m_i5k@Kx7a3HhKS@8AX?IVb*Nc@$Q;~sz Ofx*+&&t;ucLK6V@d?;1` literal 0 HcmV?d00001 diff --git a/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3_srgb_lossless.html b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3_srgb_lossless.html new file mode 100644 index 00000000000..e1f755c5740 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3_srgb_lossless.html @@ -0,0 +1,8 @@ + +JPEG XL test + + + + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3a_srgb_lossless.html b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3a_srgb_lossless.html new file mode 100644 index 00000000000..efc8fd9a9f2 --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/3x3a_srgb_lossless.html @@ -0,0 +1,8 @@ + +JPEG XL test + + + + + + diff --git a/Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3_srgb_lossless.jxl b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3_srgb_lossless.jxl new file mode 100644 index 0000000000000000000000000000000000000000..bb9cf0bb2e487fb09bc394827a72f2f1c6275082 GIT binary patch literal 66 zcmey*B_JRWuycEt5(f(-!wCj&iEh!L9ELy7-#T4pX%XjWn!CAHST^BBUF{pT7Z;0b Yu5G`!-+RRa1@pi2FTR)bSrWtm09~^kF8}}l literal 0 HcmV?d00001 diff --git a/Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3a_srgb_lossless.jxl b/Tests/LibWeb/Ref/input/wpt-import/jpegxl/resources/3x3a_srgb_lossless.jxl new file mode 100644 index 0000000000000000000000000000000000000000..6bbb43d8e72f94a548d1cc38dc58981123d11979 GIT binary patch literal 66 zcmey*B_Ob2K~cV_D~Esp!wCj&iEdFY)uuOP4nL>mzGQIzd0qcmn1hz7wB6f&yZsto XntloMf9>!2rK%t2J!b|70|Ns9H#-?G literal 0 HcmV?d00001