18 #include <exiv2/exiv2.hpp>
19 #include <QRegularExpression>
22 #if 0 // needs further work on the correct casting of tag values to QVariant values!
23 QVariantMap QgsExifTools::readTags(
const QString &imagePath )
25 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
29 image->readMetadata();
30 Exiv2::ExifData &exifData = image->exifData();
31 if ( exifData.empty() )
37 Exiv2::ExifData::const_iterator end = exifData.end();
38 for ( Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i )
40 const QString key = QString::fromStdString( i->key() );
42 switch ( i->typeId() )
44 case Exiv2::asciiString:
47 case Exiv2::directory:
49 val = QString::fromStdString( i->toString() );
52 case Exiv2::unsignedLong:
53 case Exiv2::signedLong:
54 val = QVariant::fromValue( i->toLong() );
57 case Exiv2::tiffDouble:
58 case Exiv2::tiffFloat:
59 val = QVariant::fromValue( i->toFloat() );
62 case Exiv2::unsignedShort:
63 case Exiv2::signedShort:
64 val = QVariant::fromValue(
static_cast< int >( i->toLong() ) );
67 case Exiv2::unsignedRational:
68 case Exiv2::signedRational:
69 case Exiv2::unsignedByte:
70 case Exiv2::signedByte:
71 case Exiv2::undefined:
79 case Exiv2::invalidTypeId:
80 case Exiv2::lastTypeId:
81 val = QString::fromStdString( i->toString() );
86 res.insert( key, val );
94 double d = std::abs( val );
95 int degrees =
static_cast< int >( std::floor( d ) );
96 double m = 60 * ( d - degrees );
97 int minutes =
static_cast< int >( std::floor( m ) );
98 double s = 60 * ( m - minutes );
99 int seconds =
static_cast< int >( std::floor( s * 1000 ) );
100 return QStringLiteral(
"%1/1 %2/1 %3/1000" ).arg( degrees ).arg( minutes ).arg( seconds );
113 if ( !QFileInfo::exists( imagePath ) )
117 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
121 image->readMetadata();
122 Exiv2::ExifData &exifData = image->exifData();
124 if ( exifData.empty() )
127 Exiv2::ExifData::iterator itLatRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitudeRef" ) );
128 Exiv2::ExifData::iterator itLatVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitude" ) );
129 Exiv2::ExifData::iterator itLonRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitudeRef" ) );
130 Exiv2::ExifData::iterator itLonVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitude" ) );
132 if ( itLatRef == exifData.end() || itLatVal == exifData.end() ||
133 itLonRef == exifData.end() || itLonVal == exifData.end() )
136 auto readCoord = [](
const QString & coord )->
double
140 const QStringList parts = coord.split( QRegularExpression( QStringLiteral(
"\\s+" ) ) );
141 for (
const QString &rational : parts )
143 const QStringList pair = rational.split(
'/' );
144 if ( pair.size() != 2 )
146 res += ( pair[0].toDouble() / pair[1].toDouble() ) / div;
152 auto readRationale = [](
const QString & rational )->
double
154 const QStringList pair = rational.split(
'/' );
155 if ( pair.size() != 2 )
156 return std::numeric_limits< double >::quiet_NaN();
157 return pair[0].toDouble() / pair[1].toDouble();
160 double lat = readCoord( QString::fromStdString( itLatVal->value().toString() ) );
161 double lon = readCoord( QString::fromStdString( itLonVal->value().toString() ) );
163 const QString latRef = QString::fromStdString( itLatRef->value().toString() );
164 const QString lonRef = QString::fromStdString( itLonRef->value().toString() );
165 if ( latRef.compare( QLatin1String(
"S" ), Qt::CaseInsensitive ) == 0 )
169 if ( lonRef.compare( QLatin1String(
"W" ), Qt::CaseInsensitive ) == 0 )
176 Exiv2::ExifData::iterator itElevVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitude" ) );
177 Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitudeRef" ) );
178 if ( itElevVal != exifData.end() )
180 double elev = readRationale( QString::fromStdString( itElevVal->value().toString() ) );
181 if ( itElevRefVal != exifData.end() )
183 const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() );
184 if ( elevRef.compare( QLatin1String(
"1" ), Qt::CaseInsensitive ) == 0 )
206 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
210 image->readMetadata();
211 Exiv2::ExifData &exifData = image->exifData();
213 exifData[
"Exif.GPSInfo.GPSVersionID"] =
"2 0 0 0";
214 exifData[
"Exif.GPSInfo.GPSMapDatum"] =
"WGS-84";
219 const QString elevationString = QStringLiteral(
"%1/1000" ).arg(
static_cast< int>( std::floor( std::abs( details.
elevation ) * 1000 ) ) );
220 exifData[
"Exif.GPSInfo.GPSAltitude"] = elevationString.toStdString();
221 exifData[
"Exif.GPSInfo.GPSAltitudeRef"] = details.
elevation < 0.0 ?
"1" :
"0";
223 exifData[
"Exif.GPSInfo.GPSLatitudeRef"] = location.
y() > 0 ?
"N" :
"S";
224 exifData[
"Exif.GPSInfo.GPSLongitudeRef"] = location.
x() > 0 ?
"E" :
"W";
225 exifData[
"Exif.Image.GPSTag"] = 4908;
226 image->writeMetadata();