Browse Source

LibGfx/TIFF: Add AdobeDeflate compression support

This new compression is quite popular and uses a basic Zlib compression
to compress strips. Note that this is not part of the original TIFF
specification but in the Technical Notes from 2002:
https://web.archive.org/web/20160305055905/http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf

The test case was generated with GIMP.
Lucas CHOLLET 1 year ago
parent
commit
73c8b4865e

+ 12 - 0
Tests/LibGfx/TestImageDecoder.cpp

@@ -462,6 +462,18 @@ TEST_CASE(test_tiff_lzw)
     EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red);
 }
 
+TEST_CASE(test_tiff_defalte)
+{
+    auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/deflate.tiff"sv)));
+    EXPECT(Gfx::TIFFImageDecoderPlugin::sniff(file->bytes()));
+    auto plugin_decoder = TRY_OR_FAIL(Gfx::TIFFImageDecoderPlugin::create(file->bytes()));
+
+    auto frame = TRY_OR_FAIL(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)));

BIN
Tests/LibGfx/test-inputs/tiff/deflate.tiff


+ 16 - 0
Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp

@@ -5,11 +5,13 @@
  */
 
 #include "TIFFLoader.h"
+#include <AK/ConstrainedStream.h>
 #include <AK/Debug.h>
 #include <AK/Endian.h>
 #include <AK/String.h>
 #include <LibCompress/LZWDecoder.h>
 #include <LibCompress/PackBitsDecoder.h>
+#include <LibCompress/Zlib.h>
 #include <LibGfx/ImageFormats/CCITTDecoder.h>
 #include <LibGfx/ImageFormats/TIFFMetadata.h>
 
@@ -280,6 +282,20 @@ private:
             TRY(loop_over_pixels(move(decode_lzw_strip)));
             break;
         }
+        case Compression::AdobeDeflate: {
+            // This is an extension from the Technical Notes from 2002:
+            // https://web.archive.org/web/20160305055905/http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf
+            ByteBuffer decoded_bytes {};
+            auto decode_zlib = [&](u32 num_bytes) -> ErrorOr<ReadonlyBytes> {
+                auto stream = make<ConstrainedStream>(MaybeOwned<Stream>(*m_stream), num_bytes);
+                auto decompressed_stream = TRY(Compress::ZlibDecompressor::create(move(stream)));
+                decoded_bytes = TRY(decompressed_stream->read_until_eof(4096));
+                return decoded_bytes;
+            };
+
+            TRY(loop_over_pixels(move(decode_zlib)));
+            break;
+        }
         case Compression::PackBits: {
             // Section 9: PackBits Compression
             ByteBuffer decoded_bytes {};

+ 1 - 0
Userland/Libraries/LibGfx/TIFFGenerator.py

@@ -47,6 +47,7 @@ class Compression(EnumWithExportName):
     Group4Fax = 4
     LZW = 5
     JPEG = 6
+    AdobeDeflate = 8
     PackBits = 32773