瀏覽代碼

LibGfx/TIFF: Modify the image according to the Orientation tag

Let's use the already existing logic (ExifOrientedBitmap) to modify the
bitmap to honor the orientation tag.
Lucas CHOLLET 1 年之前
父節點
當前提交
335097e446

+ 13 - 0
Tests/LibGfx/TestImageDecoder.cpp

@@ -546,6 +546,19 @@ TEST_CASE(test_tiff_deflate)
     EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red);
 }
 
+TEST_CASE(test_tiff_orientation)
+{
+    auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/orientation.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, { 300, 400 }));
+
+    // Orientation is Rotate90Clockwise
+    EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::White);
+    EXPECT_EQ(frame.image->get_pixel(300 - 75, 60), Gfx::Color::NamedColor::Red);
+}
+
 TEST_CASE(test_tiff_packed_bits)
 {
     auto file = MUST(Core::MappedFile::map(TEST_INPUT("tiff/packed_bits.tiff"sv)));

二進制
Tests/LibGfx/test-inputs/tiff/orientation.tiff


+ 7 - 4
Userland/Libraries/LibGfx/ImageFormats/TIFFLoader.cpp

@@ -13,6 +13,7 @@
 #include <LibCompress/PackBitsDecoder.h>
 #include <LibCompress/Zlib.h>
 #include <LibGfx/ImageFormats/CCITTDecoder.h>
+#include <LibGfx/ImageFormats/ExifOrientedBitmap.h>
 #include <LibGfx/ImageFormats/TIFFMetadata.h>
 
 namespace Gfx {
@@ -69,7 +70,7 @@ public:
 
     IntSize size() const
     {
-        return { *m_metadata.image_width(), *m_metadata.image_height() };
+        return ExifOrientedBitmap::oriented_size({ *m_metadata.image_width(), *m_metadata.image_height() }, *m_metadata.orientation());
     }
 
     Metadata const& metadata() const
@@ -207,6 +208,8 @@ private:
         auto const strips_offset = *m_metadata.strip_offsets();
         auto const strip_byte_counts = *m_metadata.strip_byte_counts();
 
+        auto oriented_bitmap = TRY(ExifOrientedBitmap::create(BitmapFormat::BGRA8888, { *metadata().image_width(), *metadata().image_height() }, *metadata().orientation()));
+
         for (u32 strip_index = 0; strip_index < strips_offset.size(); ++strip_index) {
             TRY(m_stream->seek(strips_offset[strip_index]));
 
@@ -231,20 +234,20 @@ private:
                     }
 
                     last_color = color;
-                    m_bitmap->set_pixel(column, scanline, color);
+                    oriented_bitmap.set_pixel(column, scanline, color);
                 }
 
                 decoded_stream->align_to_byte_boundary();
             }
         }
 
+        m_bitmap = oriented_bitmap.bitmap();
+
         return {};
     }
 
     ErrorOr<void> decode_frame_impl()
     {
-        m_bitmap = TRY(Bitmap::create(BitmapFormat::BGRA8888, size()));
-
         switch (*m_metadata.compression()) {
         case Compression::NoCompression: {
             auto identity = [&](u32 num_bytes) {