From 06111bf6729e5c279b8bb32157fd6d309f7dd94a Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 1 Mar 2024 21:26:15 +0100 Subject: Tiff: Add message handler to pass errors/warnings through Qt logging Use TIFFClientOpenExt() and set an error/warning handler to be able to pass the output through the Qt logging system. Use qt.imageformats.tiff as the logging channel. This requires libtiff >= 4.5.0 Fixes: QTBUG-122829 Change-Id: I19d453ced9af0b6bc20988f6f1505988c1c1aa5c Reviewed-by: Qt CI Bot Reviewed-by: Eirik Aavitsland (cherry picked from commit adbede1e675be185da233673be853ced3423033c) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 123 ++++++++++++++++--------- 1 file changed, 81 insertions(+), 42 deletions(-) diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 0c6936c..ff33815 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,8 @@ extern "C" { QT_BEGIN_NAMESPACE +static Q_LOGGING_CATEGORY(lcTiff, "qt.imageformats.tiff") + tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) { QIODevice *device = static_cast(fd); @@ -99,6 +102,13 @@ public: bool openForRead(QIODevice *device); bool readHeaders(QIODevice *device); void close(); + TIFF *openInternal(const char *mode, QIODevice *device); +#if TIFFLIB_VERSION >= 20221213 + static int tiffErrorHandler(TIFF *tif, void *user_data, const char *, + const char *fmt, va_list ap); + static int tiffWarningHandler(TIFF *tif, void *user_data, const char *, + const char *fmt, va_list ap); +#endif TIFF *tiff; int compression; @@ -133,7 +143,7 @@ static QImageIOHandler::Transformations exif2Qt(int exifOrientation) case 8: // rotate 270 CW return QImageIOHandler::TransformationRotate270; } - qWarning("Invalid EXIF orientation"); + qCWarning(lcTiff, "Invalid EXIF orientation"); return QImageIOHandler::TransformationNone; } @@ -157,7 +167,7 @@ static int qt2Exif(QImageIOHandler::Transformations transformation) case QImageIOHandler::TransformationRotate270: return 8; } - qWarning("Invalid Qt image transformation"); + qCWarning(lcTiff, "Invalid Qt image transformation"); return 1; } @@ -186,10 +196,67 @@ void QTiffHandlerPrivate::close() tiff = 0; } +TIFF *QTiffHandlerPrivate::openInternal(const char *mode, QIODevice *device) +{ +// TIFFLIB_VERSION 20221213 -> 4.5.0 +#if TIFFLIB_VERSION >= 20221213 + TIFFOpenOptions *opts = TIFFOpenOptionsAlloc(); + TIFFOpenOptionsSetErrorHandlerExtR(opts, &tiffErrorHandler, this); + TIFFOpenOptionsSetWarningHandlerExtR(opts, &tiffWarningHandler, this); + auto handle = TIFFClientOpenExt("foo", + mode, + device, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc, + opts); + TIFFOpenOptionsFree(opts); +#else + auto handle = TIFFClientOpen("foo", + mode, + device, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); +#endif + return handle; +} + + +#if TIFFLIB_VERSION >= 20221213 +int QTiffHandlerPrivate::tiffErrorHandler(TIFF *tif, void *user_data, const char *, + const char *fmt, va_list ap) +{ + const auto priv = static_cast(user_data); + if (!priv || priv->tiff != tif) + return 0; + qCCritical(lcTiff) << QString::vasprintf(fmt, ap); + return 1; +} + +int QTiffHandlerPrivate::tiffWarningHandler(TIFF *tif, void *user_data, const char *, + const char *fmt, va_list ap) +{ + const auto priv = static_cast(user_data); + if (!priv || priv->tiff != tif) + return 0; + qCWarning(lcTiff) << QString::vasprintf(fmt, ap); + return 1; +} +#endif + bool QTiffHandlerPrivate::canRead(QIODevice *device) { if (!device) { - qWarning("QTiffHandler::canRead() called with no device"); + qCWarning(lcTiff, "QTiffHandler::canRead() called with no device"); return false; } @@ -213,21 +280,8 @@ bool QTiffHandlerPrivate::openForRead(QIODevice *device) if (!canRead(device)) return false; - tiff = TIFFClientOpen("foo", - "r", - device, - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); - - if (!tiff) { - return false; - } - return true; + tiff = openInternal("rh", device); + return tiff != nullptr; } bool QTiffHandlerPrivate::readHeaders(QIODevice *device) @@ -238,7 +292,10 @@ bool QTiffHandlerPrivate::readHeaders(QIODevice *device) if (!openForRead(device)) return false; - TIFFSetDirectory(tiff, currentDirectory); + if (!TIFFSetDirectory(tiff, currentDirectory)) { + close(); + return false; + } uint32_t width; uint32_t height; @@ -582,16 +639,7 @@ bool QTiffHandler::write(const QImage &image) if (!device()->isWritable()) return false; - TIFF *const tiff = TIFFClientOpen("foo", - "wB", - device(), - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); + TIFF *const tiff = d->openInternal("wB", device()); if (!tiff) return false; @@ -1064,24 +1112,15 @@ bool QTiffHandler::ensureHaveDirectoryCount() const if (d->directoryCount > 0) return true; - TIFF *tiff = TIFFClientOpen("foo", - "r", - device(), - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); + TIFF *tiff = d->openInternal("rh", device()); + if (!tiff) { device()->reset(); return false; } - do { - ++d->directoryCount; - } while (TIFFReadDirectory(tiff)); + while (TIFFReadDirectory(tiff)) + ++d->directoryCount; TIFFClose(tiff); device()->reset(); return true; -- cgit v1.2.3