From 272be6b20a9c97304946454de66c7e8bdc77844f Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Sat, 4 Nov 2023 17:22:54 -0400 Subject: [PATCH] LibGfx/TIFF: Add support for LZW compression --- Tests/LibGfx/TestImageDecoder.cpp | 12 +++++ Tests/LibGfx/test-inputs/tiff/lzw.tiff | Bin 0 -> 12455 bytes .../LibGfx/ImageFormats/TIFFLoader.cpp | 45 +++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 Tests/LibGfx/test-inputs/tiff/lzw.tiff diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index b05fc35477..fdc76d228c 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -384,6 +384,18 @@ TEST_CASE(test_tiff_uncompressed) EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red); } +TEST_CASE(test_tiff_lzw) +{ + auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/lzw.tiff"sv))); + EXPECT(Gfx::TIFFImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = MUST(Gfx::TIFFImageDecoderPlugin::create(file->bytes())); + + auto frame = expect_single_frame_of_size(*plugin_decoder, { 400, 300 }); + + EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::White); + EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red); +} + TEST_CASE(test_tiff_packed_bits) { auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/packed_bits.tiff"sv))); diff --git a/Tests/LibGfx/test-inputs/tiff/lzw.tiff b/Tests/LibGfx/test-inputs/tiff/lzw.tiff new file mode 100644 index 0000000000000000000000000000000000000000..9040f769a3e4bfbc3dfcc7adf83798e2d6ed5169 GIT binary patch literal 12455 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 literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index bc962a5c27..1e7c16210b 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace Gfx { @@ -108,10 +109,12 @@ private: }; template - ErrorOr loop_over_pixels(ByteReader&& byte_reader) + ErrorOr loop_over_pixels(ByteReader&& byte_reader, Function(u32)> initializer = {}) { for (u32 strip_index = 0; strip_index < m_strip_offsets.size(); ++strip_index) { TRY(m_stream->seek(m_strip_offsets[strip_index])); + if (initializer) + TRY(initializer(m_strip_bytes_count[strip_index])); for (u32 row = 0; row < m_rows_per_strip; row++) { auto const scanline = row + m_rows_per_strip * strip_index; if (scanline >= static_cast(m_size.height())) @@ -145,6 +148,46 @@ private: case Compression::NoCompression: TRY(loop_over_pixels([this]() { return read_value(); })); break; + case Compression::LZW: { + Vector result_buffer {}; + Optional> decoder {}; + + u16 clear_code {}; + u16 end_of_information_code {}; + + auto initializer = [&](u32 bytes) -> ErrorOr { + auto strip_stream = make(TRY(m_stream->read_in_place(bytes))); + auto lzw_stream = make(MaybeOwned(move(strip_stream))); + decoder = Compress::LZWDecoder { MaybeOwned { move(lzw_stream) }, 8, -1 }; + + clear_code = decoder->add_control_code(); + end_of_information_code = decoder->add_control_code(); + + return {}; + }; + + auto read_lzw_byte = [&]() -> ErrorOr { + while (true) { + if (!result_buffer.is_empty()) + return result_buffer.take_first(); + + auto const code = TRY(decoder->next_code()); + + if (code == clear_code) { + decoder->reset(); + continue; + } + + if (code == end_of_information_code) + return Error::from_string_literal("TIFFImageDecoderPlugin: Reached end of LZW stream"); + + result_buffer = decoder->get_output(); + } + }; + + TRY(loop_over_pixels([read_lzw_byte = move(read_lzw_byte)]() { return read_lzw_byte(); }, move(initializer))); + break; + } case Compression::PackBits: { // Section 9: PackBits Compression Optional n;