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
This commit is contained in:
Albert Astals Cid
2025-09-11 11:57:19 +02:00
parent 95f0d15e14
commit c36b4e2350
2 changed files with 34 additions and 7 deletions

View File

@ -32,6 +32,7 @@
#include <QTemporaryDir> #include <QTemporaryDir>
#include <JXRGlue.h> #include <JXRGlue.h>
#include <cfenv>
#include <cstring> #include <cstring>
Q_DECLARE_LOGGING_CATEGORY(LOG_JXRPLUGIN) 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)) { if (auto err = d->pDecoder->GetResolution(d->pDecoder, &hres, &vres)) {
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() error while reading resolution:" << err; qCWarning(LOG_JXRPLUGIN) << "JXRHandler::read() error while reading resolution:" << err;
} else { } else {
img.setDotsPerMeterX(qRound(hres * 1000 / 25.4)); std::feclearexcept(FE_ALL_EXCEPT);
img.setDotsPerMeterY(qRound(vres * 1000 / 25.4)); 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 // alpha copy mode

View File

@ -15,6 +15,8 @@
#include <QStringDecoder> #include <QStringDecoder>
#include <QTimeZone> #include <QTimeZone>
#include <cfenv>
// TIFF 6 specs // TIFF 6 specs
#define TIFF_IMAGEWIDTH 0x100 #define TIFF_IMAGEWIDTH 0x100
#define TIFF_IMAGEHEIGHT 0x101 #define TIFF_IMAGEHEIGHT 0x101
@ -1193,13 +1195,30 @@ void MicroExif::updateImageMetadata(QImage &targetImage, bool replaceExisting) c
} }
} }
static std::optional<int> 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) bool MicroExif::updateImageResolution(QImage &targetImage)
{ {
if (horizontalResolution() > 0) const std::optional<int> hdpm = convertToDotsPerMeter(horizontalResolution());
targetImage.setDotsPerMeterX(qRound(horizontalResolution() / 25.4 * 1000)); const std::optional<int> vdpm = convertToDotsPerMeter(verticalResolution());
if (verticalResolution() > 0) if (hdpm) {
targetImage.setDotsPerMeterY(qRound(verticalResolution() / 25.4 * 1000)); targetImage.setDotsPerMeterX(*hdpm);
return (horizontalResolution() > 0) || (verticalResolution() > 0); }
if (vdpm) {
targetImage.setDotsPerMeterY(*vdpm);
}
return hdpm || vdpm;
} }
MicroExif MicroExif::fromByteArray(const QByteArray &ba, bool searchHeader) MicroExif MicroExif::fromByteArray(const QByteArray &ba, bool searchHeader)