From 4f5a0227e230e91f299623bd05d1770d8ea97843 Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Sat, 4 Nov 2023 22:47:24 -0400 Subject: [PATCH] LibGfx/TIFF: Add support for the differencing predictor The differencing predictor is a different way to encode pixels in TIFF images. Every pixel is encoded as a difference with the previous column of the image, except the first column, obviously. This parameter is materialized by a new tag for which reading was also implemented. --- .../LibGfx/ImageFormats/TIFFLoader.cpp | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index 327364fff1..bc962a5c27 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -102,6 +102,11 @@ private: PackBits = 32773, }; + enum class Predictor { + None = 1, + HorizontalDifferencing = 2, + }; + template ErrorOr loop_over_pixels(ByteReader&& byte_reader) { @@ -112,8 +117,18 @@ private: if (scanline >= static_cast(m_size.height())) break; + Optional last_color {}; + for (u32 column = 0; column < static_cast(m_size.width()); ++column) { - auto const color = Color { TRY(byte_reader()), TRY(byte_reader()), TRY(byte_reader()) }; + auto color = Color { TRY(byte_reader()), TRY(byte_reader()), TRY(byte_reader()) }; + + if (m_predictor == Predictor::HorizontalDifferencing && last_color.has_value()) { + color.set_red(last_color->red() + color.red()); + color.set_green(last_color->green() + color.green()); + color.set_blue(last_color->blue() + color.blue()); + } + + last_color = color; m_bitmap->set_pixel(column, scanline, color); } } @@ -528,6 +543,23 @@ private: }); } break; + case 317: + // Predictor + if (type != Type::UnsignedShort || count != 1) + return Error::from_string_literal("TIFFImageDecoderPlugin: Invalid tag 317"); + + TRY(value[0].visit( + [this](u16 const& predictor) -> ErrorOr { + if (predictor != 1 && predictor != 2) + return Error::from_string_literal("TIFFImageDecoderPlugin: Invalid predictor value"); + + m_predictor = static_cast(predictor); + return {}; + }, + [&](auto const&) -> ErrorOr { + VERIFY_NOT_REACHED(); + })); + break; default: dbgln_if(TIFF_DEBUG, "Unknown tag: {}", tag); } @@ -545,6 +577,7 @@ private: Array m_bits_per_sample {}; Compression m_compression {}; + Predictor m_predictor {}; Vector m_strip_offsets {}; u32 m_rows_per_strip {}; Vector m_strip_bytes_count {};