diff options
author | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2023-01-04 18:06:57 +0100 |
---|---|---|
committer | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2023-01-13 14:46:28 +0100 |
commit | cd92d76e9dcd98f4fc974c796453459779393bdc (patch) | |
tree | e17023e7102b82a4664746af431a64c29b1eb68e /src | |
parent | 8ea7335aeb7a9209e633e273942ba93a63189db7 (diff) | |
download | qtimageformats-cd92d76e9dcd98f4fc974c796453459779393bdc.tar.gz |
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.
Pick-to: 6.5 6.4 6.2 5.15
Change-Id: Id6a746546e069da9910cacd4a4996c669c72cbab
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/imageformats/tiff/qtiffhandler.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index fa84364..d01e888 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -9,6 +9,8 @@ #include <qimage.h> #include <qvariant.h> #include <qvarlengtharray.h> +#include <qbuffer.h> +#include <qfiledevice.h> extern "C" { #include "tiffio.h" @@ -57,13 +59,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)); } |