diff options
author | Andreas Kling <kling@serenityos.org> | 2022-02-14 17:55:35 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-14 18:39:20 +0100 |
commit | f7f7aa6986e000f0da497c6fe1eddf7465ab2d4d (patch) | |
tree | b03b336bd042a4334f8fd6df5095d1087bad2511 /Userland | |
parent | 5c7f11f1cdda1c7ac89ecf4c21371f5628ee158d (diff) | |
download | serenity-f7f7aa6986e000f0da497c6fe1eddf7465ab2d4d.zip |
LibGfx/PNG: Respect the tRNS chunk transparency with color type 2
For PNG color type 2 (TrueColor), if there's a tRNS chunk, it specifies
an R/G/B triplet in the image bit depth. This triplet acts as the
transparency value, and should yield transparent pixels wherever that
specific color value is present.
We now support this. :^)
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibGfx/PNGLoader.cpp | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/Userland/Libraries/LibGfx/PNGLoader.cpp b/Userland/Libraries/LibGfx/PNGLoader.cpp index 8d723d4768..4dc64e36a6 100644 --- a/Userland/Libraries/LibGfx/PNGLoader.cpp +++ b/Userland/Libraries/LibGfx/PNGLoader.cpp @@ -54,6 +54,8 @@ struct [[gnu::packed]] Triplet { T r; T g; T b; + + bool operator==(Triplet const& other) const = default; }; template<typename T> @@ -313,6 +315,24 @@ ALWAYS_INLINE static void unpack_triplets_without_alpha(PNGLoadingContext& conte } } +template<typename T> +ALWAYS_INLINE static void unpack_triplets_with_transparency_value(PNGLoadingContext& context, Triplet<T> transparency_value) +{ + for (int y = 0; y < context.height; ++y) { + auto* triplets = reinterpret_cast<const Triplet<T>*>(context.scanlines[y].data.data()); + for (int i = 0; i < context.width; ++i) { + auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; + pixel.r = triplets[i].r; + pixel.g = triplets[i].g; + pixel.b = triplets[i].b; + if (triplets[i] == transparency_value) + pixel.a = 0x00; + else + pixel.a = 0xff; + } + } +} + NEVER_INLINE FLATTEN static ErrorOr<void> unfilter(PNGLoadingContext& context) { // First unpack the scanlines to RGBA: @@ -352,12 +372,24 @@ NEVER_INLINE FLATTEN static ErrorOr<void> unfilter(PNGLoadingContext& context) } break; case 2: - if (context.bit_depth == 8) { - unpack_triplets_without_alpha<u8>(context); - } else if (context.bit_depth == 16) { - unpack_triplets_without_alpha<u16>(context); + if (context.palette_transparency_data.size() == 6) { + if (context.bit_depth == 8) { + unpack_triplets_with_transparency_value<u8>(context, Triplet<u8> { context.palette_transparency_data[0], context.palette_transparency_data[2], context.palette_transparency_data[4] }); + } else if (context.bit_depth == 16) { + u16 tr = context.palette_transparency_data[0] | context.palette_transparency_data[1] << 8; + u16 tg = context.palette_transparency_data[2] | context.palette_transparency_data[3] << 8; + u16 tb = context.palette_transparency_data[4] | context.palette_transparency_data[5] << 8; + unpack_triplets_with_transparency_value<u16>(context, Triplet<u16> { tr, tg, tb }); + } else { + VERIFY_NOT_REACHED(); + } } else { - VERIFY_NOT_REACHED(); + if (context.bit_depth == 8) + unpack_triplets_without_alpha<u8>(context); + else if (context.bit_depth == 16) + unpack_triplets_without_alpha<u16>(context); + else + VERIFY_NOT_REACHED(); } break; case 6: |