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 );
106 if ( !QFileInfo::exists( imagePath ) )
110 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
114 image->readMetadata();
115 Exiv2::ExifData &exifData = image->exifData();
117 if ( exifData.empty() )
120 Exiv2::ExifData::iterator itLatRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitudeRef" ) );
121 Exiv2::ExifData::iterator itLatVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitude" ) );
122 Exiv2::ExifData::iterator itLonRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitudeRef" ) );
123 Exiv2::ExifData::iterator itLonVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitude" ) );
125 if ( itLatRef == exifData.end() || itLatVal == exifData.end() ||
126 itLonRef == exifData.end() || itLonVal == exifData.end() )
129 auto readCoord = [](
const QString & coord )->
double 133 const QStringList parts = coord.split( QRegularExpression( QStringLiteral(
"\\s+" ) ) );
134 for (
const QString &rational : parts )
136 const QStringList pair = rational.split(
'/' );
137 if ( pair.size() != 2 )
139 res += ( pair[0].toDouble() / pair[1].toDouble() ) / div;
145 auto readRationale = [](
const QString & rational )->
double 147 const QStringList pair = rational.split(
'/' );
148 if ( pair.size() != 2 )
149 return std::numeric_limits< double >::quiet_NaN();
150 return pair[0].toDouble() / pair[1].toDouble();
153 double lat = readCoord( QString::fromStdString( itLatVal->value().toString() ) );
154 double lon = readCoord( QString::fromStdString( itLonVal->value().toString() ) );
156 const QString latRef = QString::fromStdString( itLatRef->value().toString() );
157 const QString lonRef = QString::fromStdString( itLonRef->value().toString() );
158 if ( latRef.compare( QLatin1String(
"S" ), Qt::CaseInsensitive ) == 0 )
162 if ( lonRef.compare( QLatin1String(
"W" ), Qt::CaseInsensitive ) == 0 )
169 Exiv2::ExifData::iterator itElevVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitude" ) );
170 Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitudeRef" ) );
171 if ( itElevVal != exifData.end() )
173 double elev = readRationale( QString::fromStdString( itElevVal->value().toString() ) );
174 if ( itElevRefVal != exifData.end() )
176 const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() );
177 if ( elevRef.compare( QLatin1String(
"1" ), Qt::CaseInsensitive ) == 0 )
199 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
203 image->readMetadata();
204 Exiv2::ExifData &exifData = image->exifData();
206 exifData[
"Exif.GPSInfo.GPSVersionID"] =
"2 0 0 0";
207 exifData[
"Exif.GPSInfo.GPSMapDatum"] =
"WGS-84";
212 const QString elevationString = QStringLiteral(
"%1/1000" ).arg( static_cast< int>( std::floor( std::abs( details.
elevation ) * 1000 ) ) );
213 exifData[
"Exif.GPSInfo.GPSAltitude"] = elevationString.toStdString();
214 exifData[
"Exif.GPSInfo.GPSAltitudeRef"] = details.
elevation < 0.0 ?
"1" :
"0";
216 exifData[
"Exif.GPSInfo.GPSLatitudeRef"] = location.
y() > 0 ?
"N" :
"S";
217 exifData[
"Exif.GPSInfo.GPSLongitudeRef"] = location.
x() > 0 ?
"E" :
"W";
218 exifData[
"Exif.Image.GPSTag"] = 4908;
219 image->writeMetadata();
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.