summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-02-14 17:55:35 +0100
committerAndreas Kling <kling@serenityos.org>2022-02-14 18:39:20 +0100
commitf7f7aa6986e000f0da497c6fe1eddf7465ab2d4d (patch)
treeb03b336bd042a4334f8fd6df5095d1087bad2511 /Userland
parent5c7f11f1cdda1c7ac89ecf4c21371f5628ee158d (diff)
downloadserenity-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.cpp42
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: