From 1ede4f249de8fcb756a622ca3fa517c6a8c6356f Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Thu, 30 Nov 2023 23:00:41 -0500 Subject: [PATCH] LibGfx/TIFF: Decode all PackedBits beforehand This change doesn't change much on its own. The idea behind this refactoring is to separate the sample reading from the decoding step. The decoder returning data byte per byte was fine as we only support 8 bits images, but this assumption won't hold for a long time. So let's decode everything beforehand and strictly partition the sample reading code somewhere else. --- .../LibGfx/ImageFormats/TIFFLoader.cpp | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index a39e5a5e324..95dec186481 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -156,20 +156,31 @@ private: } case Compression::PackBits: { // Section 9: PackBits Compression - Optional n; - Optional saved_byte; - auto read_packed_byte = [&]() -> ErrorOr { - while (true) { + OwnPtr strip_stream; + ByteBuffer decoded_bytes {}; + u32 read_head {}; + + auto initializer = [&](u32 num_bytes) -> ErrorOr { + strip_stream = make(TRY(m_stream->read_in_place(num_bytes))); + + decoded_bytes.clear(); + read_head = 0; + + Optional n {}; + Optional saved_byte {}; + + while (strip_stream->remaining() > 0 || saved_byte.has_value()) { if (!n.has_value()) - n = TRY(read_value()); + n = TRY(strip_stream->read_value()); if (n.value() >= 0 && !saved_byte.has_value()) { n.value() = n.value() - 1; if (n.value() == -1) n.clear(); - return read_value(); + decoded_bytes.append(TRY(strip_stream->read_value())); + continue; } if (n.value() == -128) { @@ -178,22 +189,28 @@ private: } if (!saved_byte.has_value()) - saved_byte = TRY(read_value()); + saved_byte = TRY(strip_stream->read_value()); n.value() = n.value() + 1; - auto const byte_backup = *saved_byte; + decoded_bytes.append(*saved_byte); if (n == 1) { saved_byte.clear(); n.clear(); } - - return byte_backup; } + + return {}; }; - TRY(loop_over_pixels(move(read_packed_byte))); + auto read_packed_byte = [&]() -> ErrorOr { + if (read_head < decoded_bytes.size()) + return decoded_bytes[read_head++]; + return Error::from_string_literal("TIFFImageDecoderPlugin: Reached end of PackedBits stream"); + }; + + TRY(loop_over_pixels(move(read_packed_byte), move(initializer))); break; } default: