From c36b4e235076042b12642d6b62de58193267a8b4 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 11 Sep 2025 11:57:19 +0200 Subject: [PATCH] Use std::lround instead of qRound qRound will assert if the resulting integer is out of range, by using lround we can ask if the rounding range failed --- src/imageformats/jxr.cpp | 12 ++++++++++-- src/imageformats/microexif.cpp | 29 ++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/imageformats/jxr.cpp b/src/imageformats/jxr.cpp index 90f7524..7df9ffe 100644 --- a/src/imageformats/jxr.cpp +++ b/src/imageformats/jxr.cpp @@ -32,6 +32,7 @@ #include #include +#include #include Q_DECLARE_LOGGING_CATEGORY(LOG_JXRPLUGIN) @@ -977,8 +978,15 @@ bool JXRHandler::read(QImage *outImage) if (auto err = d->pDecoder->GetResolution(d->pDecoder, &hres, &vres)) { qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() error while reading resolution:" << err; } else { - img.setDotsPerMeterX(qRound(hres * 1000 / 25.4)); - img.setDotsPerMeterY(qRound(vres * 1000 / 25.4)); + std::feclearexcept(FE_ALL_EXCEPT); + const int hdpm = std::lround(hres * 1000 / 25.4); + const int vdpm = std::lround(vres * 1000 / 25.4); + if (std::fetestexcept(FE_INVALID)) { + qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() resolution is out of range:" << hres << vres; + } else { + img.setDotsPerMeterX(hdpm); + img.setDotsPerMeterY(vdpm); + } } // alpha copy mode diff --git a/src/imageformats/microexif.cpp b/src/imageformats/microexif.cpp index 876ea47..110c982 100644 --- a/src/imageformats/microexif.cpp +++ b/src/imageformats/microexif.cpp @@ -15,6 +15,8 @@ #include #include +#include + // TIFF 6 specs #define TIFF_IMAGEWIDTH 0x100 #define TIFF_IMAGEHEIGHT 0x101 @@ -1193,13 +1195,30 @@ void MicroExif::updateImageMetadata(QImage &targetImage, bool replaceExisting) c } } +static std::optional convertToDotsPerMeter(const double value) +{ + if (value <= 0) { + return {}; + } + std::feclearexcept(FE_ALL_EXCEPT); + const int rounded = std::lround(value / 25.4 * 1000); + if (std::fetestexcept(FE_INVALID)) { + return {}; + } + return rounded; +} + bool MicroExif::updateImageResolution(QImage &targetImage) { - if (horizontalResolution() > 0) - targetImage.setDotsPerMeterX(qRound(horizontalResolution() / 25.4 * 1000)); - if (verticalResolution() > 0) - targetImage.setDotsPerMeterY(qRound(verticalResolution() / 25.4 * 1000)); - return (horizontalResolution() > 0) || (verticalResolution() > 0); + const std::optional hdpm = convertToDotsPerMeter(horizontalResolution()); + const std::optional vdpm = convertToDotsPerMeter(verticalResolution()); + if (hdpm) { + targetImage.setDotsPerMeterX(*hdpm); + } + if (vdpm) { + targetImage.setDotsPerMeterY(*vdpm); + } + return hdpm || vdpm; } MicroExif MicroExif::fromByteArray(const QByteArray &ba, bool searchHeader)