56QVariant 
decodeXmpData( 
const QString &key, Exiv2::XmpData::const_iterator &it )
 
   59  if ( key == QLatin1String( 
"Xmp.xmp.MetadataDate" ) ||
 
   60       key == QLatin1String( 
"Xmp.xmp.CreateDate" ) ||
 
   61       key == QLatin1String( 
"Xmp.xmp.ModifyDate" ) )
 
   63    val = QVariant::fromValue( QDateTime::fromString( QString::fromStdString( it->toString() ), Qt::ISODate ) );
 
   67    switch ( it->typeId() )
 
   69      case Exiv2::asciiString:
 
   72      case Exiv2::directory:
 
   74        val = QString::fromStdString( it->toString() );
 
   77      case Exiv2::unsignedLong:
 
   78      case Exiv2::signedLong:
 
   79      case Exiv2::unsignedLongLong:
 
   80      case Exiv2::signedLongLong:
 
   81#if EXIV2_TEST_VERSION (0, 28, 0) 
   82        val = QVariant::fromValue( it->toUint32() );
 
   84        val = QVariant::fromValue( it->toLong() );
 
   88      case Exiv2::tiffDouble:
 
   89      case Exiv2::tiffFloat:
 
   90        val = QVariant::fromValue( it->toFloat() );
 
   93      case Exiv2::unsignedShort:
 
   94      case Exiv2::signedShort:
 
   95      case Exiv2::unsignedByte:
 
   96      case Exiv2::signedByte:
 
   99#if EXIV2_TEST_VERSION (0, 28, 0) 
  100        val = QVariant::fromValue( 
static_cast< int >( it->toUint32() ) );
 
  102        val = QVariant::fromValue( 
static_cast< int >( it->toLong() ) );
 
  108        const Exiv2::DateValue::Date date = 
static_cast< const Exiv2::DateValue *
>( &it->value() )->getDate();
 
  109        val = QVariant::fromValue( QDate::fromString( QStringLiteral( 
"%1-%2-%3" ).arg( date.year )
 
  110                                   .arg( QString::number( date.month ).rightJustified( 2, 
'0' ) )
 
  111                                   .arg( QString::number( date.day ).rightJustified( 2, 
'0' ) ), QLatin1String( 
"yyyy-MM-dd" ) ) );
 
  117        const Exiv2::TimeValue::Time time = 
static_cast< const Exiv2::TimeValue *
>( &it->value() )->getTime();
 
  118        val = QVariant::fromValue( QTime::fromString( QStringLiteral( 
"%1:%2:%3" ).arg( QString::number( time.hour ).rightJustified( 2, 
'0' ) )
 
  119                                   .arg( QString::number( time.minute ).rightJustified( 2, 
'0' ) )
 
  120                                   .arg( QString::number( time.second ).rightJustified( 2, 
'0' ) ), QLatin1String( 
"hh:mm:ss" ) ) );
 
  124      case Exiv2::unsignedRational:
 
  125      case Exiv2::signedRational:
 
  127        if ( it->count() == 1 )
 
  129          val = QVariant::fromValue( 
readRational( it->value() ) );
 
  133          val = QString::fromStdString( it->toString() );
 
  138      case Exiv2::undefined:
 
  143      case Exiv2::invalidTypeId:
 
  144      case Exiv2::lastTypeId:
 
  145        val = QString::fromStdString( it->toString() );
 
 
  153QVariant 
decodeExifData( 
const QString &key, Exiv2::ExifData::const_iterator &it )
 
  157  if ( key == QLatin1String( 
"Exif.GPSInfo.GPSLatitude" ) ||
 
  158       key == QLatin1String( 
"Exif.GPSInfo.GPSLongitude" ) ||
 
  159       key == QLatin1String( 
"Exif.GPSInfo.GPSDestLatitude" ) ||
 
  160       key == QLatin1String( 
"Exif.GPSInfo.GPSDestLongitude" ) )
 
  164  else if ( key == QLatin1String( 
"Exif.GPSInfo.GPSTimeStamp" ) )
 
  166    const QStringList parts = QString::fromStdString( it->toString() ).split( QRegularExpression( QStringLiteral( 
"\\s+" ) ) );
 
  167    if ( parts.size() == 3 )
 
  169      const int hour = std::max( 0, std::min( 23, 
static_cast< int >( 
readRational( it->value(), 0 ) ) ) );
 
  170      const int minute = std::max( 0, std::min( 59, 
static_cast< int >( 
readRational( it->value(), 1 ) ) ) );
 
  171      const int second = std::max( 0, std::min( 59, 
static_cast< int >( 
readRational( it->value(), 2 ) ) ) );
 
  173      val = QVariant::fromValue( QTime::fromString( QStringLiteral( 
"%1:%2:%3" )
 
  174                                 .arg( QString::number( hour ).rightJustified( 2, 
'0' ) )
 
  175                                 .arg( QString::number( minute ).rightJustified( 2, 
'0' ) )
 
  176                                 .arg( QString::number( second ).rightJustified( 2, 
'0' ) ), QLatin1String( 
"hh:mm:ss" ) ) );
 
  179  else if ( key == QLatin1String( 
"Exif.GPSInfo.GPSDateStamp" ) )
 
  181    val = QVariant::fromValue( QDate::fromString( QString::fromStdString( it->toString() ), QLatin1String( 
"yyyy:MM:dd" ) ) );
 
  183  else if ( key == QLatin1String( 
"Exif.Image.DateTime" ) ||
 
  184            key == QLatin1String( 
"Exif.Image.DateTime" ) ||
 
  185            key == QLatin1String( 
"Exif.Photo.DateTimeDigitized" ) ||
 
  186            key == QLatin1String( 
"Exif.Photo.DateTimeOriginal" ) )
 
  188    val = QVariant::fromValue( QDateTime::fromString( QString::fromStdString( it->toString() ), QLatin1String( 
"yyyy:MM:dd hh:mm:ss" ) ) );
 
  192    switch ( it->typeId() )
 
  194      case Exiv2::asciiString:
 
  197      case Exiv2::directory:
 
  199        val = QString::fromStdString( it->toString() );
 
  202      case Exiv2::unsignedLong:
 
  203      case Exiv2::signedLong:
 
  204      case Exiv2::unsignedLongLong:
 
  205      case Exiv2::signedLongLong:
 
  206#if EXIV2_TEST_VERSION (0, 28, 0) 
  207        val = QVariant::fromValue( it->toUint32() );
 
  209        val = QVariant::fromValue( it->toLong() );
 
  213      case Exiv2::tiffDouble:
 
  214      case Exiv2::tiffFloat:
 
  215        val = QVariant::fromValue( it->toFloat() );
 
  218      case Exiv2::unsignedShort:
 
  219      case Exiv2::signedShort:
 
  220      case Exiv2::unsignedByte:
 
  221      case Exiv2::signedByte:
 
  223      case Exiv2::tiffIfd8:
 
  224#if EXIV2_TEST_VERSION (0, 28, 0) 
  225        val = QVariant::fromValue( 
static_cast< int >( it->toUint32() ) );
 
  227        val = QVariant::fromValue( 
static_cast< int >( it->toLong() ) );
 
  233        const Exiv2::DateValue::Date date = 
static_cast< const Exiv2::DateValue *
>( &it->value() )->getDate();
 
  234        val = QVariant::fromValue( QDate::fromString( QStringLiteral( 
"%1-%2-%3" ).arg( date.year )
 
  235                                   .arg( QString::number( date.month ).rightJustified( 2, 
'0' ) )
 
  236                                   .arg( QString::number( date.day ).rightJustified( 2, 
'0' ) ), QLatin1String( 
"yyyy-MM-dd" ) ) );
 
  242        const Exiv2::TimeValue::Time time = 
static_cast< const Exiv2::TimeValue *
>( &it->value() )->getTime();
 
  243        val = QVariant::fromValue( QTime::fromString( QStringLiteral( 
"%1:%2:%3" ).arg( QString::number( time.hour ).rightJustified( 2, 
'0' ) )
 
  244                                   .arg( QString::number( time.minute ).rightJustified( 2, 
'0' ) )
 
  245                                   .arg( QString::number( time.second ).rightJustified( 2, 
'0' ) ), QLatin1String( 
"hh:mm:ss" ) ) );
 
  249      case Exiv2::unsignedRational:
 
  250      case Exiv2::signedRational:
 
  252        if ( it->count() == 1 )
 
  254          val = QVariant::fromValue( 
readRational( it->value() ) );
 
  258          val = QString::fromStdString( it->toString() );
 
  263      case Exiv2::undefined:
 
  268      case Exiv2::invalidTypeId:
 
  269      case Exiv2::lastTypeId:
 
  270        val = QString::fromStdString( it->toString() );
 
 
  290  if ( !QFileInfo::exists( imagePath ) )
 
  295    std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
 
  296    if ( !image || key.isEmpty() )
 
  299    image->readMetadata();
 
  301    if ( key.startsWith( QLatin1String( 
"Xmp." ) ) )
 
  303      Exiv2::XmpData &xmpData = image->xmpData();
 
  304      if ( xmpData.empty() )
 
  308      Exiv2::XmpData::const_iterator i = xmpData.findKey( Exiv2::XmpKey( key.toUtf8().constData() ) );
 
  309      return i != xmpData.end() ? 
decodeXmpData( key, i ) : QVariant();
 
  313      Exiv2::ExifData &exifData = image->exifData();
 
  314      if ( exifData.empty() )
 
  318      Exiv2::ExifData::const_iterator i = exifData.findKey( Exiv2::ExifKey( key.toUtf8().constData() ) );
 
  319      return i != exifData.end() ? 
decodeExifData( key, i ) : QVariant();
 
 
  330  if ( !QFileInfo::exists( imagePath ) )
 
  331    return QVariantMap();
 
  336    std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
 
  338      return QVariantMap();
 
  339    image->readMetadata();
 
  341    Exiv2::ExifData &exifData = image->exifData();
 
  342    if ( !exifData.empty() )
 
  344      const Exiv2::ExifData::const_iterator end = exifData.end();
 
  345      for ( Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i )
 
  347        const QString key = QString::fromStdString( i->key() );
 
  352    Exiv2::XmpData &xmpData = image->xmpData();
 
  353    if ( !xmpData.empty() )
 
  355      const Exiv2::XmpData::const_iterator end = xmpData.end();
 
  356      for ( Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i )
 
  358        const QString key = QString::fromStdString( i->key() );
 
  367    return QVariantMap();
 
 
  381  if ( !QFileInfo::exists( imagePath ) )
 
  385    std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
 
  389    image->readMetadata();
 
  390    Exiv2::ExifData &exifData = image->exifData();
 
  392    if ( exifData.empty() )
 
  395    const Exiv2::ExifData::iterator itLatRef = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSLatitudeRef" ) );
 
  396    const Exiv2::ExifData::iterator itLatVal = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSLatitude" ) );
 
  397    const Exiv2::ExifData::iterator itLonRef = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSLongitudeRef" ) );
 
  398    const Exiv2::ExifData::iterator itLonVal = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSLongitude" ) );
 
  400    if ( itLatRef == exifData.end() || itLatVal == exifData.end() ||
 
  401         itLonRef == exifData.end() || itLonVal == exifData.end() )
 
  407    const QString latRef = QString::fromStdString( itLatRef->value().toString() );
 
  408    const QString lonRef = QString::fromStdString( itLonRef->value().toString() );
 
  409    if ( latRef.compare( QLatin1String( 
"S" ), Qt::CaseInsensitive ) == 0 )
 
  413    if ( lonRef.compare( QLatin1String( 
"W" ), Qt::CaseInsensitive ) == 0 )
 
  420    const Exiv2::ExifData::iterator itElevVal = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSAltitude" ) );
 
  421    const Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey( 
"Exif.GPSInfo.GPSAltitudeRef" ) );
 
  422    if ( itElevVal != exifData.end() )
 
  425      if ( itElevRefVal != exifData.end() )
 
  427        const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() );
 
  428        if ( elevRef.compare( QLatin1String( 
"1" ), Qt::CaseInsensitive ) == 0 )
 
 
  483    std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) );
 
  487    QVariant actualValue;
 
  488    bool actualValueIsUShort = 
false;
 
  489    if ( tag == QLatin1String( 
"Exif.GPSInfo.GPSLatitude" ) ||
 
  490         tag == QLatin1String( 
"Exif.GPSInfo.GPSLongitude" ) ||
 
  491         tag == QLatin1String( 
"Exif.GPSInfo.GPSDestLatitude" ) ||
 
  492         tag == QLatin1String( 
"Exif.GPSInfo.GPSDestLongitude" ) )
 
  496    else if ( tag == QLatin1String( 
"Exif.GPSInfo.GPSAltitude" ) )
 
  498      actualValue = QStringLiteral( 
"%1/1000" ).arg( 
static_cast< int>( std::floor( std::abs( value.toDouble() ) * 1000 ) ) );
 
  500    else if ( tag == QLatin1String( 
"Exif.Image.Orientation" ) )
 
  502      actualValueIsUShort = 
true;
 
  505    else if ( value.userType() == QMetaType::Type::QDateTime )
 
  507      const QDateTime dateTime = value.toDateTime();
 
  508      if ( tag == QLatin1String( 
"Exif.Image.DateTime" ) ||
 
  509           tag == QLatin1String( 
"Exif.Image.DateTime" ) ||
 
  510           tag == QLatin1String( 
"Exif.Photo.DateTimeDigitized" ) ||
 
  511           tag == QLatin1String( 
"Exif.Photo.DateTimeOriginal" ) )
 
  513        actualValue = dateTime.toString( QStringLiteral( 
"yyyy:MM:dd hh:mm:ss" ) );
 
  517        actualValue = dateTime.toString( Qt::ISODate );
 
  520    else if ( value.userType() == QMetaType::Type::QDate )
 
  522      const QDate date = value.toDate();
 
  523      if ( tag == QLatin1String( 
"Exif.GPSInfo.GPSDateStamp" ) )
 
  525        actualValue = date.toString( QStringLiteral( 
"yyyy:MM:dd" ) );
 
  529        actualValue = date.toString( QStringLiteral( 
"yyyy-MM-dd" ) );
 
  532    else if ( value.userType() == QMetaType::Type::QTime )
 
  534      const QTime time = value.toTime();
 
  535      if ( tag == QLatin1String( 
"Exif.GPSInfo.GPSTimeStamp" ) )
 
  537        actualValue = QStringLiteral( 
"%1/1 %2/1 %3/1" ).arg( time.hour() ).arg( time.minute() ).arg( time.second() );
 
  541        actualValue = time.toString( QStringLiteral( 
"HH:mm:ss" ) );
 
  549    const bool isXmp = tag.startsWith( QLatin1String( 
"Xmp." ) );
 
  550    image->readMetadata();
 
  551    if ( actualValueIsUShort )
 
  555        Exiv2::XmpData &xmpData = image->xmpData();
 
  556        xmpData[tag.toStdString()] = 
static_cast<ushort
>( actualValue.toLongLong() );
 
  560        Exiv2::ExifData &exifData = image->exifData();
 
  561        exifData[tag.toStdString()] = 
static_cast<ushort
>( actualValue.toLongLong() );
 
  564    else if ( actualValue.userType() == QMetaType::Type::Int ||
 
  565              actualValue.userType() == QMetaType::Type::LongLong )
 
  569        Exiv2::XmpData &xmpData = image->xmpData();
 
  570        xmpData[tag.toStdString()] = 
static_cast<uint32_t
>( actualValue.toLongLong() );
 
  574        Exiv2::ExifData &exifData = image->exifData();
 
  575        exifData[tag.toStdString()] = 
static_cast<uint32_t
>( actualValue.toLongLong() );
 
  578    else if ( actualValue.userType() == QMetaType::Type::UInt ||
 
  579              actualValue.userType() ==  QMetaType::Type::ULongLong )
 
  583        Exiv2::XmpData &xmpData = image->xmpData();
 
  584        xmpData[tag.toStdString()] = 
static_cast<int32_t
>( actualValue.toULongLong() );
 
  588        Exiv2::ExifData &exifData = image->exifData();
 
  589        exifData[tag.toStdString()] = 
static_cast<int32_t
>( actualValue.toULongLong() );
 
  592    else if ( actualValue.userType() == QMetaType::Type::Double )
 
  596        Exiv2::XmpData &xmpData = image->xmpData();
 
  597        xmpData[tag.toStdString()] = Exiv2::floatToRationalCast( actualValue.toFloat() );
 
  601        Exiv2::ExifData &exifData = image->exifData();
 
  602        exifData[tag.toStdString()] = Exiv2::floatToRationalCast( actualValue.toFloat() );
 
  609        Exiv2::XmpData &xmpData = image->xmpData();
 
  610        xmpData[tag.toStdString()] = actualValue.toString().toStdString();
 
  614        Exiv2::ExifData &exifData = image->exifData();
 
  615        exifData[tag.toStdString()] = actualValue.toString().toStdString();
 
  618    image->writeMetadata();