summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEirik Aavitsland <eirik.aavitsland@qt.io>2023-01-04 18:06:57 +0100
committerEirik Aavitsland <eirik.aavitsland@qt.io>2023-01-16 15:22:56 +0000
commit16f9d27557c94d84bf43d2fbbe9b37d64705fd0d (patch)
treebac0bd35513c86f73d32c898f443a32c1fb30c0e
parent0527ceeba4205a5411eef4cfbb451a6a2719935d (diff)
Implement support for file memory mapping for tiff reading
libtiff will by default attempt to establish a memory map for reading a tiff file. Implement the callbacks to establish this in Qt's tiff handler, since this will save data copying, particularly in the case where the input file is already in memory as a resource or QBuffer. Also, this makes sure that QTiffHandler utilizes libtiff's default, and hence best tested, code path for tiff decoding. Specifically, it avoids a hitting a bug that breaks reading of certain tiffs in the newly released libtiff version 4.5.0. Change-Id: Id6a746546e069da9910cacd4a4996c669c72cbab Reviewed-by: Dmitry Shachnev <mitya57@gmail.com> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit cd92d76e9dcd98f4fc974c796453459779393bdc) Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler.cpp27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 84cd138..5b5c16f 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -43,6 +43,9 @@
#include <qdebug.h>
#include <qimage.h>
#include <qglobal.h>
+#include <qbuffer.h>
+#include <qfiledevice.h>
+
extern "C" {
#include "tiffio.h"
}
@@ -90,13 +93,33 @@ toff_t qtiffSizeProc(thandle_t fd)
return static_cast<QIODevice *>(fd)->size();
}
-int qtiffMapProc(thandle_t /*fd*/, tdata_t* /*pbase*/, toff_t* /*psize*/)
+int qtiffMapProc(thandle_t fd, void **base, toff_t *size)
{
+ QIODevice *device = static_cast<QIODevice *>(fd);
+
+ QFileDevice *file = qobject_cast<QFileDevice *>(device);
+ if (file) {
+ *base = file->map(0, file->size());
+ if (*base != nullptr) {
+ *size = file->size();
+ return 1;
+ }
+ } else {
+ QBuffer *buf = qobject_cast<QBuffer *>(device);
+ if (buf) {
+ *base = const_cast<char *>(buf->data().constData());
+ *size = buf->size();
+ return 1;
+ }
+ }
return 0;
}
-void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/)
+void qtiffUnmapProc(thandle_t fd, void *base, toff_t /*size*/)
{
+ QFileDevice *file = qobject_cast<QFileDevice *>(static_cast<QIODevice *>(fd));
+ if (file && base)
+ file->unmap(static_cast<uchar *>(base));
}