diff options
author | Sandro Mani <manisandro@gmail.com> | 2017-01-01 23:49:35 +0100 |
---|---|---|
committer | Sandro Mani <manisandro@gmail.com> | 2017-01-25 09:46:19 +0000 |
commit | d2306d74850986692c02b70df0d7a6a6e933d0dc (patch) | |
tree | 76265b9485fe07706df86ddba0539383136a4eb7 | |
parent | 67e7a44a06d5d4d1c98d04f4b0e1a07583f3bfa5 (diff) | |
download | qtimageformats-d2306d74850986692c02b70df0d7a6a6e933d0dc.tar.gz |
Add support for multipage TIFF images to QTiffHandlerv5.9.0-alpha1
Allows multipage TIFF images to be read via QImageReader::jumpToImage
and QImageReader::jumpNextToImage.
[ChangeLog][QtGui][QImageReader] Support multipage TIFF images through
QImageReader
Change-Id: Id6ac68b75500148e51be11eff3d296c929d2d95c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r-- | src/plugins/imageformats/tiff/qtiffhandler.cpp | 96 | ||||
-rw-r--r-- | src/plugins/imageformats/tiff/qtiffhandler_p.h | 6 | ||||
-rw-r--r-- | tests/auto/tiff/tst_qtiff.cpp | 44 | ||||
-rw-r--r-- | tests/shared/images/tiff.qrc | 1 | ||||
-rw-r--r-- | tests/shared/images/tiff/multipage.tiff | bin | 0 -> 20238 bytes |
5 files changed, 137 insertions, 10 deletions
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 6fcf2a7..b5d80f9 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -116,6 +116,8 @@ public: uint16 photometric; bool grayscale; bool headersRead; + int currentDirectory; + int directoryCount; }; static QImageIOHandler::Transformations exif2Qt(int exifOrientation) @@ -174,6 +176,8 @@ QTiffHandlerPrivate::QTiffHandlerPrivate() , photometric(false) , grayscale(false) , headersRead(false) + , currentDirectory(0) + , directoryCount(0) { } @@ -225,6 +229,19 @@ bool QTiffHandlerPrivate::openForRead(QIODevice *device) if (!tiff) { return false; } + return true; +} + +bool QTiffHandlerPrivate::readHeaders(QIODevice *device) +{ + if (headersRead) + return true; + + if (!openForRead(device)) + return false; + + TIFFSetDirectory(tiff, currentDirectory); + uint32 width; uint32 height; if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) @@ -275,14 +292,6 @@ bool QTiffHandlerPrivate::openForRead(QIODevice *device) return true; } -bool QTiffHandlerPrivate::readHeaders(QIODevice *device) -{ - if (headersRead) - return true; - - return openForRead(device); -} - QTiffHandler::QTiffHandler() : QImageIOHandler() , d(new QTiffHandlerPrivate) @@ -308,7 +317,7 @@ bool QTiffHandler::canRead(QIODevice *device) bool QTiffHandler::read(QImage *image) { // Open file and read headers if it hasn't already been done. - if (!d->openForRead(device())) + if (!d->readHeaders(device())) return false; QImage::Format format = d->format; @@ -438,7 +447,6 @@ bool QTiffHandler::read(QImage *image) } } - d->close(); return true; } @@ -739,6 +747,45 @@ bool QTiffHandler::supportsOption(ImageOption option) const || option == TransformedByDefault; } +bool QTiffHandler::jumpToNextImage() +{ + if (!ensureHaveDirectoryCount()) + return false; + if (d->currentDirectory >= d->directoryCount - 1) + return false; + + d->headersRead = false; + ++d->currentDirectory; + return true; +} + +bool QTiffHandler::jumpToImage(int imageNumber) +{ + if (!ensureHaveDirectoryCount()) + return false; + if (imageNumber < 0 || imageNumber >= d->directoryCount) + return false; + + if (d->currentDirectory != imageNumber) { + d->headersRead = false; + d->currentDirectory = imageNumber; + } + return true; +} + +int QTiffHandler::imageCount() const +{ + if (!ensureHaveDirectoryCount()) + return 1; + + return d->directoryCount; +} + +int QTiffHandler::currentImageNumber() const +{ + return d->currentDirectory; +} + void QTiffHandler::convert32BitOrder(void *buffer, int width) { uint32 *target = reinterpret_cast<uint32 *>(buffer); @@ -751,4 +798,33 @@ void QTiffHandler::convert32BitOrder(void *buffer, int width) | ((p & 0x000000ff) << 16); } } + +bool QTiffHandler::ensureHaveDirectoryCount() const +{ + if (d->directoryCount > 0) + return true; + + TIFF *tiff = TIFFClientOpen("foo", + "r", + device(), + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); + if (!tiff) { + device()->reset(); + return false; + } + + do { + ++d->directoryCount; + } while (TIFFReadDirectory(tiff)); + TIFFClose(tiff); + device()->reset(); + return true; +} + QT_END_NAMESPACE diff --git a/src/plugins/imageformats/tiff/qtiffhandler_p.h b/src/plugins/imageformats/tiff/qtiffhandler_p.h index f362a90..311ae46 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler_p.h +++ b/src/plugins/imageformats/tiff/qtiffhandler_p.h @@ -63,6 +63,11 @@ public: void setOption(ImageOption option, const QVariant &value) override; bool supportsOption(ImageOption option) const override; + bool jumpToNextImage() Q_DECL_OVERRIDE; + bool jumpToImage(int imageNumber) Q_DECL_OVERRIDE; + int imageCount() const Q_DECL_OVERRIDE; + int currentImageNumber() const Q_DECL_OVERRIDE; + enum Compression { NoCompression = 0, LzwCompression = 1 @@ -70,6 +75,7 @@ public: private: void convert32BitOrder(void *buffer, int width); const QScopedPointer<QTiffHandlerPrivate> d; + bool ensureHaveDirectoryCount() const; }; QT_END_NAMESPACE diff --git a/tests/auto/tiff/tst_qtiff.cpp b/tests/auto/tiff/tst_qtiff.cpp index 8e3d0c9..65cc56c 100644 --- a/tests/auto/tiff/tst_qtiff.cpp +++ b/tests/auto/tiff/tst_qtiff.cpp @@ -78,6 +78,9 @@ private slots: void resolution_data(); void resolution(); + void multipage_data(); + void multipage(); + private: QString prefix; }; @@ -513,5 +516,46 @@ void tst_qtiff::resolution() QCOMPARE(expectedDotsPerMeterY, generatedImage.dotsPerMeterY()); } +void tst_qtiff::multipage_data() +{ + QTest::addColumn<QString>("filename"); + QTest::addColumn<int>("expectedNumPages"); + QTest::addColumn<QVector<QSize>>("expectedSizes"); + + QVector<QSize> sizes = QVector<QSize>() << QSize(640, 480) << QSize(800, 600) << QSize(320, 240); + QTest::newRow("3 page TIFF") << ("multipage.tiff") << 3 << sizes; +} + +void tst_qtiff::multipage() +{ + QFETCH(QString, filename); + QFETCH(int, expectedNumPages); + QFETCH(QVector<QSize>, expectedSizes); + + QImageReader reader(prefix + filename); + QCOMPARE(reader.imageCount(), expectedNumPages); + + // Test jumpToImage, currentImageNumber and whether the actual image is correct + QCOMPARE(reader.jumpToImage(-1), false); + for (int i = 0; i < expectedNumPages; ++i) { + reader.jumpToImage(i); + QCOMPARE(reader.currentImageNumber(), i); + QSize size = reader.size(); + QCOMPARE(size.width(), expectedSizes[i].width()); + QCOMPARE(size.height(), expectedSizes[i].height()); + QImage image = reader.read(); + QVERIFY2(!image.isNull(), qPrintable(reader.errorString())); + } + QCOMPARE(reader.jumpToImage(expectedNumPages), false); + + // Test jumpToNextImage + reader.jumpToImage(0); + QCOMPARE(reader.currentImageNumber(), 0); + for (int i = 0; i < expectedNumPages - 1; ++i) { + QCOMPARE(reader.jumpToNextImage(), true); + } + QCOMPARE(reader.jumpToNextImage(), false); +} + QTEST_MAIN(tst_qtiff) #include "tst_qtiff.moc" diff --git a/tests/shared/images/tiff.qrc b/tests/shared/images/tiff.qrc index 8fcab8b..c98a72c 100644 --- a/tests/shared/images/tiff.qrc +++ b/tests/shared/images/tiff.qrc @@ -21,6 +21,7 @@ <file>tiff/mono_orientation_6.tiff</file> <file>tiff/mono_orientation_7.tiff</file> <file>tiff/mono_orientation_8.tiff</file> + <file>tiff/multipage.tiff</file> <file>tiff/original_indexed.tiff</file> <file>tiff/original_mono.tiff</file> <file>tiff/original_rgb.tiff</file> diff --git a/tests/shared/images/tiff/multipage.tiff b/tests/shared/images/tiff/multipage.tiff Binary files differnew file mode 100644 index 0000000..0c2f266 --- /dev/null +++ b/tests/shared/images/tiff/multipage.tiff |