From 7c5b131e0e1befcdb7e40adeea0d114cbf9d7d2c Mon Sep 17 00:00:00 2001 From: Michael Schmuki Date: Sun, 30 Jun 2024 14:55:34 +0200 Subject: [PATCH 1/2] Respect Exiv2::Value type (e.g. Exiv2::unsignedRational) in readRational of QgsExifTools (fixes #57942) --- src/core/raster/qgsexiftools.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/core/raster/qgsexiftools.cpp b/src/core/raster/qgsexiftools.cpp index d7e5f6a0664e..b411aa9fcaa0 100644 --- a/src/core/raster/qgsexiftools.cpp +++ b/src/core/raster/qgsexiftools.cpp @@ -23,10 +23,21 @@ #include #include -double readRationale( const Exiv2::Value &value, long n = 0 ) +double readRational( const Exiv2::Value &value, long n = 0 ) { const Exiv2::Rational rational = value.toRational( n ); - return static_cast< double >( rational.first ) / rational.second; + const auto numerator = rational.first; + const auto denominator = rational.second; + double res = 0; + if ( value.typeId() == Exiv2::unsignedRational ) + { + res = static_cast< double >( static_cast( numerator ) ) / static_cast( denominator ); + } + else + { + res = static_cast< double >( numerator ) / denominator; + } + return res; }; double readCoordinate( const Exiv2::Value &value ) @@ -35,7 +46,7 @@ double readCoordinate( const Exiv2::Value &value ) double div = 1; for ( int i = 0; i < 3; i++ ) { - res += readRationale( value, i ) / div; + res += readRational( value, i ) / div; div *= 60; } return res; @@ -114,7 +125,7 @@ QVariant decodeXmpData( const QString &key, Exiv2::XmpData::const_iterator &it ) { if ( it->count() == 1 ) { - val = QVariant::fromValue( readRationale( it->value() ) ); + val = QVariant::fromValue( readRational( it->value() ) ); } else { @@ -154,9 +165,9 @@ QVariant decodeExifData( const QString &key, Exiv2::ExifData::const_iterator &it const QStringList parts = QString::fromStdString( it->toString() ).split( QRegularExpression( QStringLiteral( "\\s+" ) ) ); if ( parts.size() == 3 ) { - const int hour = readRationale( it->value(), 0 ); - const int minute = readRationale( it->value(), 1 ); - const int second = readRationale( it->value(), 2 ); + const int hour = readRational( it->value(), 0 ); + const int minute = readRational( it->value(), 1 ); + const int second = readRational( it->value(), 2 ); val = QVariant::fromValue( QTime::fromString( QStringLiteral( "%1:%2:%3" ) .arg( QString::number( hour ).rightJustified( 2, '0' ) ) .arg( QString::number( minute ).rightJustified( 2, '0' ) ) @@ -238,7 +249,7 @@ QVariant decodeExifData( const QString &key, Exiv2::ExifData::const_iterator &it { if ( it->count() == 1 ) { - val = QVariant::fromValue( readRationale( it->value() ) ); + val = QVariant::fromValue( readRational( it->value() ) ); } else { @@ -408,7 +419,7 @@ QgsPoint QgsExifTools::getGeoTag( const QString &imagePath, bool &ok ) const Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSAltitudeRef" ) ); if ( itElevVal != exifData.end() ) { - double elev = readRationale( itElevVal->value() ); + double elev = readRational( itElevVal->value() ); if ( itElevRefVal != exifData.end() ) { const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() ); From e44e589639bb643f08de70be1e785a3a5306b29e Mon Sep 17 00:00:00 2001 From: Michael Schmuki Date: Tue, 2 Jul 2024 18:57:01 +0200 Subject: [PATCH 2/2] Explicitly cast Exif GPSTimeStamp from double to int and min/max hh:mm:ss values --- src/core/raster/qgsexiftools.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/raster/qgsexiftools.cpp b/src/core/raster/qgsexiftools.cpp index b411aa9fcaa0..e46a9e5b78d2 100644 --- a/src/core/raster/qgsexiftools.cpp +++ b/src/core/raster/qgsexiftools.cpp @@ -165,9 +165,10 @@ QVariant decodeExifData( const QString &key, Exiv2::ExifData::const_iterator &it const QStringList parts = QString::fromStdString( it->toString() ).split( QRegularExpression( QStringLiteral( "\\s+" ) ) ); if ( parts.size() == 3 ) { - const int hour = readRational( it->value(), 0 ); - const int minute = readRational( it->value(), 1 ); - const int second = readRational( it->value(), 2 ); + const int hour = std::max( 0, std::min( 23, static_cast< int >( readRational( it->value(), 0 ) ) ) ); + const int minute = std::max( 0, std::min( 59, static_cast< int >( readRational( it->value(), 1 ) ) ) ); + const int second = std::max( 0, std::min( 59, static_cast< int >( readRational( it->value(), 2 ) ) ) ); + val = QVariant::fromValue( QTime::fromString( QStringLiteral( "%1:%2:%3" ) .arg( QString::number( hour ).rightJustified( 2, '0' ) ) .arg( QString::number( minute ).rightJustified( 2, '0' ) )