From e4bba2fab94304be391b6f0ba747bc958295e25e Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 22 Dec 2021 01:12:51 +0100 Subject: [PATCH] LibGfx: Keep alpha value of previous pixel for QOI_OP_RGB chunk I accidentally skipped this part of the spec in the QOI decoder: > The alpha value remains unchanged from the previous pixel. This led to incorrect rendering of some images with transparency, visible in form of a horizontal line of non-transparent pixels (that shouldn't exist), e.g. for the following chunk sequence: - QOI_OP_RGBA with alpha = 0 - QOI_OP_RGB - QOI_OP_RUN The QOI_OP_RGB should 'inherit' the alpha value of the previous QOI_OP_RGBA chunk, instead of always setting it to 255. I'm unsure why the encoder added the QOI_OP_RGB chunk to the specific image where the bug was noticed in the first place - they effectively both had fully transparent color values. --- Userland/Libraries/LibGfx/QOILoader.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibGfx/QOILoader.cpp b/Userland/Libraries/LibGfx/QOILoader.cpp index d1b79a034a..3186b8dfa0 100644 --- a/Userland/Libraries/LibGfx/QOILoader.cpp +++ b/Userland/Libraries/LibGfx/QOILoader.cpp @@ -34,14 +34,16 @@ static ErrorOr decode_qoi_header(InputMemoryStream& stream) return header; } -static ErrorOr decode_qoi_op_rgb(InputMemoryStream& stream) +static ErrorOr decode_qoi_op_rgb(InputMemoryStream& stream, Color pixel) { u8 bytes[4]; stream >> Bytes { &bytes, array_size(bytes) }; if (stream.handle_any_error()) return Error::from_string_literal("Invalid QOI image: end of stream while reading QOI_OP_RGB chunk"sv); VERIFY(bytes[0] == QOI_OP_RGB); - return Color { bytes[1], bytes[2], bytes[3] }; + + // The alpha value remains unchanged from the previous pixel. + return Color { bytes[1], bytes[2], bytes[3], pixel.alpha() }; } static ErrorOr decode_qoi_op_rgba(InputMemoryStream& stream) @@ -163,7 +165,7 @@ static ErrorOr> decode_qoi_image(InputMemoryStream& stream if (stream.handle_any_error()) return Error::from_string_literal("Invalid QOI image: end of stream while reading chunk tag"sv); if (tag == QOI_OP_RGB) - pixel = TRY(decode_qoi_op_rgb(stream)); + pixel = TRY(decode_qoi_op_rgb(stream, pixel)); else if (tag == QOI_OP_RGBA) pixel = TRY(decode_qoi_op_rgba(stream)); else if ((tag & QOI_MASK_2) == QOI_OP_INDEX)