44QVariant
decodeXmpData(
const QString &key, Exiv2::XmpData::const_iterator &it )
47 if ( key == QLatin1String(
"Xmp.xmp.MetadataDate" ) ||
48 key == QLatin1String(
"Xmp.xmp.CreateDate" ) ||
49 key == QLatin1String(
"Xmp.xmp.ModifyDate" ) )
51 val = QVariant::fromValue( QDateTime::fromString( QString::fromStdString( it->toString() ), Qt::ISODate ) );
55 switch ( it->typeId() )
57 case Exiv2::asciiString:
60 case Exiv2::directory:
62 val = QString::fromStdString( it->toString() );
65 case Exiv2::unsignedLong:
66 case Exiv2::signedLong:
67 case Exiv2::unsignedLongLong:
68 case Exiv2::signedLongLong:
69#if EXIV2_TEST_VERSION (0, 28, 0)
70 val = QVariant::fromValue( it->toUint32() );
72 val = QVariant::fromValue( it->toLong() );
76 case Exiv2::tiffDouble:
77 case Exiv2::tiffFloat:
78 val = QVariant::fromValue( it->toFloat() );
81 case Exiv2::unsignedShort:
82 case Exiv2::signedShort:
83 case Exiv2::unsignedByte:
84 case Exiv2::signedByte:
87#if EXIV2_TEST_VERSION (0, 28, 0)
88 val = QVariant::fromValue(
static_cast< int >( it->toUint32() ) );
90 val = QVariant::fromValue(
static_cast< int >( it->toLong() ) );
96 const Exiv2::DateValue::Date date =
static_cast< const Exiv2::DateValue *
>( &it->value() )->getDate();
97 val = QVariant::fromValue( QDate::fromString( QStringLiteral(
"%1-%2-%3" ).arg( date.year )
98 .arg( QString::number( date.month ).rightJustified( 2,
'0' ) )
99 .arg( QString::number( date.day ).rightJustified( 2,
'0' ) ), QLatin1String(
"yyyy-MM-dd" ) ) );
105 const Exiv2::TimeValue::Time time =
static_cast< const Exiv2::TimeValue *
>( &it->value() )->getTime();
106 val = QVariant::fromValue( QTime::fromString( QStringLiteral(
"%1:%2:%3" ).arg( QString::number( time.hour ).rightJustified( 2,
'0' ) )
107 .arg( QString::number( time.minute ).rightJustified( 2,
'0' ) )
108 .arg( QString::number( time.second ).rightJustified( 2,
'0' ) ), QLatin1String(
"hh:mm:ss" ) ) );
112 case Exiv2::unsignedRational:
113 case Exiv2::signedRational:
115 if ( it->count() == 1 )
121 val = QString::fromStdString( it->toString() );
126 case Exiv2::undefined:
131 case Exiv2::invalidTypeId:
132 case Exiv2::lastTypeId:
133 val = QString::fromStdString( it->toString() );
141QVariant
decodeExifData(
const QString &key, Exiv2::ExifData::const_iterator &it )
145 if ( key == QLatin1String(
"Exif.GPSInfo.GPSLatitude" ) ||
146 key == QLatin1String(
"Exif.GPSInfo.GPSLongitude" ) ||
147 key == QLatin1String(
"Exif.GPSInfo.GPSDestLatitude" ) ||
148 key == QLatin1String(
"Exif.GPSInfo.GPSDestLongitude" ) )
152 else if ( key == QLatin1String(
"Exif.GPSInfo.GPSTimeStamp" ) )
154 const QStringList parts = QString::fromStdString( it->toString() ).split( QRegularExpression( QStringLiteral(
"\\s+" ) ) );
155 if ( parts.size() == 3 )
160 val = QVariant::fromValue( QTime::fromString( QStringLiteral(
"%1:%2:%3" )
161 .arg( QString::number( hour ).rightJustified( 2,
'0' ) )
162 .arg( QString::number( minute ).rightJustified( 2,
'0' ) )
163 .arg( QString::number( second ).rightJustified( 2,
'0' ) ), QLatin1String(
"hh:mm:ss" ) ) );
166 else if ( key == QLatin1String(
"Exif.GPSInfo.GPSDateStamp" ) )
168 val = QVariant::fromValue( QDate::fromString( QString::fromStdString( it->toString() ), QLatin1String(
"yyyy:MM:dd" ) ) );
170 else if ( key == QLatin1String(
"Exif.Image.DateTime" ) ||
171 key == QLatin1String(
"Exif.Image.DateTime" ) ||
172 key == QLatin1String(
"Exif.Photo.DateTimeDigitized" ) ||
173 key == QLatin1String(
"Exif.Photo.DateTimeOriginal" ) )
175 val = QVariant::fromValue( QDateTime::fromString( QString::fromStdString( it->toString() ), QLatin1String(
"yyyy:MM:dd hh:mm:ss" ) ) );
179 switch ( it->typeId() )
181 case Exiv2::asciiString:
184 case Exiv2::directory:
186 val = QString::fromStdString( it->toString() );
189 case Exiv2::unsignedLong:
190 case Exiv2::signedLong:
191 case Exiv2::unsignedLongLong:
192 case Exiv2::signedLongLong:
193#if EXIV2_TEST_VERSION (0, 28, 0)
194 val = QVariant::fromValue( it->toUint32() );
196 val = QVariant::fromValue( it->toLong() );
200 case Exiv2::tiffDouble:
201 case Exiv2::tiffFloat:
202 val = QVariant::fromValue( it->toFloat() );
205 case Exiv2::unsignedShort:
206 case Exiv2::signedShort:
207 case Exiv2::unsignedByte:
208 case Exiv2::signedByte:
210 case Exiv2::tiffIfd8:
211#if EXIV2_TEST_VERSION (0, 28, 0)
212 val = QVariant::fromValue(
static_cast< int >( it->toUint32() ) );
214 val = QVariant::fromValue(
static_cast< int >( it->toLong() ) );
220 const Exiv2::DateValue::Date date =
static_cast< const Exiv2::DateValue *
>( &it->value() )->getDate();
221 val = QVariant::fromValue( QDate::fromString( QStringLiteral(
"%1-%2-%3" ).arg( date.year )
222 .arg( QString::number( date.month ).rightJustified( 2,
'0' ) )
223 .arg( QString::number( date.day ).rightJustified( 2,
'0' ) ), QLatin1String(
"yyyy-MM-dd" ) ) );
229 const Exiv2::TimeValue::Time time =
static_cast< const Exiv2::TimeValue *
>( &it->value() )->getTime();
230 val = QVariant::fromValue( QTime::fromString( QStringLiteral(
"%1:%2:%3" ).arg( QString::number( time.hour ).rightJustified( 2,
'0' ) )
231 .arg( QString::number( time.minute ).rightJustified( 2,
'0' ) )
232 .arg( QString::number( time.second ).rightJustified( 2,
'0' ) ), QLatin1String(
"hh:mm:ss" ) ) );
236 case Exiv2::unsignedRational:
237 case Exiv2::signedRational:
239 if ( it->count() == 1 )
245 val = QString::fromStdString( it->toString() );
250 case Exiv2::undefined:
255 case Exiv2::invalidTypeId:
256 case Exiv2::lastTypeId:
257 val = QString::fromStdString( it->toString() );
277 if ( !QFileInfo::exists( imagePath ) )
282 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
283 if ( !image || key.isEmpty() )
286 image->readMetadata();
288 if ( key.startsWith( QLatin1String(
"Xmp." ) ) )
290 Exiv2::XmpData &xmpData = image->xmpData();
291 if ( xmpData.empty() )
295 Exiv2::XmpData::const_iterator i = xmpData.findKey( Exiv2::XmpKey( key.toUtf8().constData() ) );
296 return i != xmpData.end() ?
decodeXmpData( key, i ) : QVariant();
300 Exiv2::ExifData &exifData = image->exifData();
301 if ( exifData.empty() )
305 Exiv2::ExifData::const_iterator i = exifData.findKey( Exiv2::ExifKey( key.toUtf8().constData() ) );
306 return i != exifData.end() ?
decodeExifData( key, i ) : QVariant();
317 if ( !QFileInfo::exists( imagePath ) )
318 return QVariantMap();
323 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
325 return QVariantMap();
326 image->readMetadata();
328 Exiv2::ExifData &exifData = image->exifData();
329 if ( !exifData.empty() )
331 const Exiv2::ExifData::const_iterator end = exifData.end();
332 for ( Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i )
334 const QString key = QString::fromStdString( i->key() );
339 Exiv2::XmpData &xmpData = image->xmpData();
340 if ( !xmpData.empty() )
342 const Exiv2::XmpData::const_iterator end = xmpData.end();
343 for ( Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i )
345 const QString key = QString::fromStdString( i->key() );
354 return QVariantMap();
368 if ( !QFileInfo::exists( imagePath ) )
372 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
376 image->readMetadata();
377 Exiv2::ExifData &exifData = image->exifData();
379 if ( exifData.empty() )
382 const Exiv2::ExifData::iterator itLatRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitudeRef" ) );
383 const Exiv2::ExifData::iterator itLatVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitude" ) );
384 const Exiv2::ExifData::iterator itLonRef = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitudeRef" ) );
385 const Exiv2::ExifData::iterator itLonVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitude" ) );
387 if ( itLatRef == exifData.end() || itLatVal == exifData.end() ||
388 itLonRef == exifData.end() || itLonVal == exifData.end() )
394 const QString latRef = QString::fromStdString( itLatRef->value().toString() );
395 const QString lonRef = QString::fromStdString( itLonRef->value().toString() );
396 if ( latRef.compare( QLatin1String(
"S" ), Qt::CaseInsensitive ) == 0 )
400 if ( lonRef.compare( QLatin1String(
"W" ), Qt::CaseInsensitive ) == 0 )
407 const Exiv2::ExifData::iterator itElevVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitude" ) );
408 const Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitudeRef" ) );
409 if ( itElevVal != exifData.end() )
412 if ( itElevRefVal != exifData.end() )
414 const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() );
415 if ( elevRef.compare( QLatin1String(
"1" ), Qt::CaseInsensitive ) == 0 )
470 std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
474 QVariant actualValue;
475 if ( tag == QLatin1String(
"Exif.GPSInfo.GPSLatitude" ) ||
476 tag == QLatin1String(
"Exif.GPSInfo.GPSLongitude" ) ||
477 tag == QLatin1String(
"Exif.GPSInfo.GPSDestLatitude" ) ||
478 tag == QLatin1String(
"Exif.GPSInfo.GPSDestLongitude" ) )
482 else if ( tag == QLatin1String(
"Exif.GPSInfo.GPSAltitude" ) )
484 actualValue = QStringLiteral(
"%1/1000" ).arg(
static_cast< int>( std::floor( std::abs( value.toDouble() ) * 1000 ) ) );
486 else if ( value.type() == QVariant::DateTime )
488 const QDateTime dateTime = value.toDateTime();
489 if ( tag == QLatin1String(
"Exif.Image.DateTime" ) ||
490 tag == QLatin1String(
"Exif.Image.DateTime" ) ||
491 tag == QLatin1String(
"Exif.Photo.DateTimeDigitized" ) ||
492 tag == QLatin1String(
"Exif.Photo.DateTimeOriginal" ) )
494 actualValue = dateTime.toString( QStringLiteral(
"yyyy:MM:dd hh:mm:ss" ) );
498 actualValue = dateTime.toString( Qt::ISODate );
501 else if ( value.type() == QVariant::Date )
503 const QDate date = value.toDate();
504 if ( tag == QLatin1String(
"Exif.GPSInfo.GPSDateStamp" ) )
506 actualValue = date.toString( QStringLiteral(
"yyyy:MM:dd" ) );
510 actualValue = date.toString( QStringLiteral(
"yyyy-MM-dd" ) );
513 else if ( value.type() == QVariant::Time )
515 const QTime time = value.toTime();
516 if ( tag == QLatin1String(
"Exif.GPSInfo.GPSTimeStamp" ) )
518 actualValue = QStringLiteral(
"%1/1 %2/1 %3/1" ).arg( time.hour() ).arg( time.minute() ).arg( time.second() );
522 actualValue = time.toString( QStringLiteral(
"HH:mm:ss" ) );
530 const bool isXmp = tag.startsWith( QLatin1String(
"Xmp." ) );
531 image->readMetadata();
532 if ( actualValue.type() == QVariant::Int ||
533 actualValue.type() == QVariant::LongLong )
537 Exiv2::XmpData &xmpData = image->xmpData();
538 xmpData[tag.toStdString()] =
static_cast<uint32_t
>( actualValue.toLongLong() );
542 Exiv2::ExifData &exifData = image->exifData();
543 exifData[tag.toStdString()] =
static_cast<uint32_t
>( actualValue.toLongLong() );
546 if ( actualValue.type() == QVariant::UInt ||
547 actualValue.type() == QVariant::ULongLong )
551 Exiv2::XmpData &xmpData = image->xmpData();
552 xmpData[tag.toStdString()] =
static_cast<int32_t
>( actualValue.toULongLong() );
556 Exiv2::ExifData &exifData = image->exifData();
557 exifData[tag.toStdString()] =
static_cast<int32_t
>( actualValue.toULongLong() );
560 else if ( actualValue.type() == QVariant::Double )
564 Exiv2::XmpData &xmpData = image->xmpData();
565 xmpData[tag.toStdString()] = Exiv2::floatToRationalCast( actualValue.toFloat() );
569 Exiv2::ExifData &exifData = image->exifData();
570 exifData[tag.toStdString()] = Exiv2::floatToRationalCast( actualValue.toFloat() );
577 Exiv2::XmpData &xmpData = image->xmpData();
578 xmpData[tag.toStdString()] = actualValue.toString().toStdString();
582 Exiv2::ExifData &exifData = image->exifData();
583 exifData[tag.toStdString()] = actualValue.toString().toStdString();
586 image->writeMetadata();