diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index 7df82a5b50..07211bc0cd 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -382,6 +382,18 @@ TEST_CASE(test_tiff_uncompressed) 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))); + 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_webp_simple_lossy) { auto file = MUST(Core::MappedFile::map(TEST_INPUT("webp/simple-vp8.webp"sv))); diff --git a/Tests/LibGfx/test-inputs/tiff/packed_bits.tiff b/Tests/LibGfx/test-inputs/tiff/packed_bits.tiff new file mode 100644 index 0000000000..c66c918374 Binary files /dev/null and b/Tests/LibGfx/test-inputs/tiff/packed_bits.tiff differ diff --git a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp index df2df3352d..327364fff1 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp @@ -130,8 +130,50 @@ private: case Compression::NoCompression: TRY(loop_over_pixels([this]() { return read_value(); })); break; + case Compression::PackBits: { + // Section 9: PackBits Compression + Optional n; + Optional saved_byte; + + auto read_packed_byte = [&]() -> ErrorOr { + while (true) { + if (!n.has_value()) + n = TRY(read_value()); + + if (n.value() >= 0 && !saved_byte.has_value()) { + n.value() = n.value() - 1; + if (n.value() == -1) + n.clear(); + + return read_value(); + } + + if (n.value() == -128) { + n.clear(); + continue; + } + + if (!saved_byte.has_value()) + saved_byte = TRY(read_value()); + + n.value() = n.value() + 1; + + auto const byte_backup = *saved_byte; + + if (n == 1) { + saved_byte.clear(); + n.clear(); + } + + return byte_backup; + } + }; + + TRY(loop_over_pixels(move(read_packed_byte))); + break; + } default: - return Error::from_string_literal("Compressed TIFF are not supported yet :^)"); + return Error::from_string_literal("This compression type is not supported yet :^)"); } return {};