summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandro Mani <manisandro@gmail.com>2017-01-01 23:49:35 +0100
committerSandro Mani <manisandro@gmail.com>2017-01-25 09:46:19 +0000
commitd2306d74850986692c02b70df0d7a6a6e933d0dc (patch)
tree76265b9485fe07706df86ddba0539383136a4eb7
parent67e7a44a06d5d4d1c98d04f4b0e1a07583f3bfa5 (diff)
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.cpp96
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler_p.h6
-rw-r--r--tests/auto/tiff/tst_qtiff.cpp44
-rw-r--r--tests/shared/images/tiff.qrc1
-rw-r--r--tests/shared/images/tiff/multipage.tiffbin0 -> 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
new file mode 100644
index 0000000..0c2f266
--- /dev/null
+++ b/tests/shared/images/tiff/multipage.tiff
Binary files differ