From ac9f56b31dacc35dd2007caee69a9cf521ed8410 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Mon, 17 Aug 2009 16:12:12 +0200 Subject: Add support for the orientation of tiff images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The orientation tag was ignored for tiff images. The tag is now used to rotate the image before providing it to the user. The orientation of indexed an mono images is done completely manually. The orientation of other type is done in conjunction to the mirroring already performed by libtiff. Task-number: 258526 Reviewed-by: Samuel Rødal --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 107 ++++++++++++++++++++- .../tiff_oriented/indexed_orientation_1.tiff | Bin 0 -> 7740 bytes .../tiff_oriented/indexed_orientation_2.tiff | Bin 0 -> 9570 bytes .../tiff_oriented/indexed_orientation_3.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_4.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_5.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_6.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_7.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_8.tiff | Bin 0 -> 11392 bytes .../images/tiff_oriented/mono_orientation_1.tiff | Bin 0 -> 2382 bytes .../images/tiff_oriented/mono_orientation_2.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_3.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_4.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_5.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_6.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_7.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_8.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/original_indexed.tiff | Bin 0 -> 5922 bytes .../images/tiff_oriented/original_mono.tiff | Bin 0 -> 786 bytes .../images/tiff_oriented/original_rgb.tiff | Bin 0 -> 12608 bytes .../images/tiff_oriented/rgb_orientation_1.tiff | Bin 0 -> 15560 bytes .../images/tiff_oriented/rgb_orientation_2.tiff | Bin 0 -> 17972 bytes .../images/tiff_oriented/rgb_orientation_3.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_4.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_5.tiff | Bin 0 -> 17648 bytes .../images/tiff_oriented/rgb_orientation_6.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_7.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_8.tiff | Bin 0 -> 17324 bytes tests/auto/qimagereader/tst_qimagereader.cpp | 45 +++++++++ 29 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index ec8a483..59edaf4 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -98,6 +98,43 @@ void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/) { } +// for 32 bits images +inline void rotate_right_mirror_horizontal(QImage *const image)// rotate right->mirrored horizontal +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const uint32 *originalPixel = reinterpret_cast(image->bits()); + uint32 *const generatedPixels = reinterpret_cast(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = col * height + row; + generatedPixels[idx] = *originalPixel; + ++originalPixel; + } + } + *image = generated; +} + +inline void rotate_right_mirror_vertical(QImage *const image) // rotate right->mirrored vertical +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const int lastCol = width - 1; + const int lastRow = height - 1; + const uint32 *pixel = reinterpret_cast(image->bits()); + uint32 *const generatedBits = reinterpret_cast(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = (lastCol - col) * height + (lastRow - row); + generatedBits[idx] = *pixel; + ++pixel; + } + } + *image = generated; +} + QTiffHandler::QTiffHandler() : QImageIOHandler() { compression = NoCompression; @@ -223,7 +260,8 @@ bool QTiffHandler::read(QImage *image) if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) *image = QImage(width, height, QImage::Format_ARGB32); if (!image->isNull()) { - if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, 0)) { + const int stopOnError = 1; + if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, stopOnError)) { for (uint32 y=0; yscanLine(y), width); } else { @@ -262,6 +300,73 @@ bool QTiffHandler::read(QImage *image) } } + // rotate the image if the orientation is defined in the file + uint16 orientationTag; + if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag)) { + if (image->format() == QImage::Format_ARGB32) { + // TIFFReadRGBAImageOriented() flip the image but does not rotate them + switch (orientationTag) { + case 5: + rotate_right_mirror_horizontal(image); + break; + case 6: + rotate_right_mirror_vertical(image); + break; + case 7: + rotate_right_mirror_horizontal(image); + break; + case 8: + rotate_right_mirror_vertical(image); + break; + } + } else { + switch (orientationTag) { + case 1: // default orientation + break; + case 2: // mirror horizontal + *image = image->mirrored(true, false); + break; + case 3: // mirror both + *image = image->mirrored(true, true); + break; + case 4: // mirror vertical + *image = image->mirrored(false, true); + break; + case 5: // rotate right mirror horizontal + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(true, false); + break; + } + case 6: // rotate right + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + break; + } + case 7: // rotate right, mirror vertical + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(false, true); + break; + } + case 8: // rotate left + { + QMatrix transformation; + transformation.rotate(270); + *image = image->transformed(transformation); + break; + } + } + } + } + + TIFFClose(tiff); return true; } diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff new file mode 100644 index 0000000..3fcb8a9 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff new file mode 100644 index 0000000..6f3e9d5 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff new file mode 100644 index 0000000..aab9cf2 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff new file mode 100644 index 0000000..aad96ff Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff new file mode 100644 index 0000000..05d23dc Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff new file mode 100644 index 0000000..9ffe7fc Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff new file mode 100644 index 0000000..eeeb019 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff new file mode 100644 index 0000000..87cf2fd Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff new file mode 100644 index 0000000..3b589b2 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff new file mode 100644 index 0000000..9a66223 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff new file mode 100644 index 0000000..eed2423 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff new file mode 100644 index 0000000..055480e Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff new file mode 100644 index 0000000..b4d0974 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff new file mode 100644 index 0000000..3b1e02a Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff new file mode 100644 index 0000000..b752c74 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff new file mode 100644 index 0000000..e228d05 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff new file mode 100644 index 0000000..7507e52 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff new file mode 100644 index 0000000..8ff9db8 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff new file mode 100644 index 0000000..321ea3e Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff new file mode 100644 index 0000000..2756a82 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff new file mode 100644 index 0000000..ae9af09 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff new file mode 100644 index 0000000..a2f4325 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff new file mode 100644 index 0000000..f35bfc4 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff new file mode 100644 index 0000000..70e5478 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff new file mode 100644 index 0000000..b2635fe Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff new file mode 100644 index 0000000..1fb0cd9 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff new file mode 100644 index 0000000..666b1b4 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index dad771b..ba3d83e 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -149,6 +149,9 @@ private slots: void tiffCompression_data(); void tiffCompression(); void tiffEndianness(); + + void tiffOrientation_data(); + void tiffOrientation(); #endif void autoDetectImageFormat(); @@ -1308,6 +1311,48 @@ void tst_QImageReader::tiffEndianness() QCOMPARE(littleEndian, bigEndian); } +void tst_QImageReader::tiffOrientation_data() +{ + QTest::addColumn("expected"); + QTest::addColumn("oriented"); + QTest::newRow("Indexed TIFF, orientation1") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_1.tiff"; + QTest::newRow("Indexed TIFF, orientation2") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_2.tiff"; + QTest::newRow("Indexed TIFF, orientation3") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_3.tiff"; + QTest::newRow("Indexed TIFF, orientation4") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_4.tiff"; + QTest::newRow("Indexed TIFF, orientation5") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_5.tiff"; + QTest::newRow("Indexed TIFF, orientation6") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_6.tiff"; + QTest::newRow("Indexed TIFF, orientation7") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_7.tiff"; + QTest::newRow("Indexed TIFF, orientation8") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_8.tiff"; + + QTest::newRow("Mono TIFF, orientation1") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_1.tiff"; + QTest::newRow("Mono TIFF, orientation2") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_2.tiff"; + QTest::newRow("Mono TIFF, orientation3") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_3.tiff"; + QTest::newRow("Mono TIFF, orientation4") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_4.tiff"; + QTest::newRow("Mono TIFF, orientation5") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_5.tiff"; + QTest::newRow("Mono TIFF, orientation6") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_6.tiff"; + QTest::newRow("Mono TIFF, orientation7") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_7.tiff"; + QTest::newRow("Mono TIFF, orientation8") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_8.tiff"; + + QTest::newRow("RGB TIFF, orientation1") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_1.tiff"; + QTest::newRow("RGB TIFF, orientation2") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_2.tiff"; + QTest::newRow("RGB TIFF, orientation3") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_3.tiff"; + QTest::newRow("RGB TIFF, orientation4") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_4.tiff"; + QTest::newRow("RGB TIFF, orientation5") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_5.tiff"; + QTest::newRow("RGB TIFF, orientation6") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_6.tiff"; + QTest::newRow("RGB TIFF, orientation7") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_7.tiff"; + QTest::newRow("RGB TIFF, orientation8") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_8.tiff"; +} + +void tst_QImageReader::tiffOrientation() +{ + QFETCH(QString, expected); + QFETCH(QString, oriented); + + QImage expectedImage(prefix + expected); + QImage orientedImage(prefix + oriented); + QCOMPARE(expectedImage, orientedImage); +} + #endif void tst_QImageReader::dotsPerMeter_data() -- cgit v0.12