//for diagnostic void PrintTag(Exiv2::ExifData::iterator itr) { std::cout << itr->value() << " (" << itr->typeName() << ", size: " << itr->count() << ")" << std::endl; if(itr->count()>1) { std::cout << "["; for(long i=0; i<itr->count(); i++) { std::cout << itr->toFloat(i) << ","; } std::cout << "]" << std::endl; }; };
QString Previewimage::getExifKey(QString key, Exiv2::ExifData *exifData){ // returns string represented by exif key if(exifData == 0) return QString(); QString ret; try { Exiv2::ExifData::iterator pos = exifData->findKey( Exiv2::ExifKey(qPrintable(key))); if (pos == exifData->end()) return QString(); else ret = QString().fromStdString(pos->value().toString()); } catch (Exiv2::Error& e) { qCritical("[Rename] %s", e.what()); } return ret; }
// ***************************************************************************** // Main int main() try { // Container for all metadata Exiv2::ExifData exifData; // ************************************************************************* // Add to the Exif data // Create a ASCII string value (note the use of create) Exiv2::Value* v = Exiv2::Value::create(Exiv2::asciiString); // Set the value to a string v->read("1999:12:31 23:59:59"); // Add the value together with its key to the Exif data container Exiv2::ExifKey key("Exif.Photo.DateTimeOriginal"); exifData.add(key, v); std::cout << "Added key \"" << key << "\", value \"" << *v << "\"\n"; // Delete the memory allocated by Value::create delete v; // Now create a more interesting value (without using the create method) Exiv2::URationalValue* rv = new Exiv2::URationalValue; // Set two rational components from a string rv->read("1/2 1/3"); // Add more elements through the extended interface of rational value rv->value_.push_back(std::make_pair(2,3)); rv->value_.push_back(std::make_pair(3,4)); // Add the key and value pair to the Exif data key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities"); exifData.add(key, rv); std::cout << "Added key \"" << key << "\", value \"" << *rv << "\"\n"; // Delete memory allocated on the heap delete rv; // ************************************************************************* // Modify Exif data // Find the timestamp metadatum by its key key = Exiv2::ExifKey("Exif.Photo.DateTimeOriginal"); Exiv2::ExifData::iterator pos = exifData.findKey(key); if (pos == exifData.end()) throw Exiv2::Error("Key not found"); // Modify the value std::string date = pos->toString(); date.replace(0,4,"2000"); pos->setValue(date); std::cout << "Modified key \"" << key << "\", new value \"" << pos->value() << "\"\n"; // Find the other key key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities"); pos = exifData.findKey(key); if (pos == exifData.end()) throw Exiv2::Error("Key not found"); // Get a pointer to a copy of the value v = pos->getValue(); // Downcast the Value pointer to its actual type rv = dynamic_cast<Exiv2::URationalValue*>(v); if (rv == 0) throw Exiv2::Error("Downcast failed"); // Modify the value directly through the interface of URationalValue rv->value_[2] = std::make_pair(88,77); // Copy the modified value back to the metadatum pos->setValue(rv); // Delete the memory allocated by getValue delete v; std::cout << "Modified key \"" << key << "\", new value \"" << pos->value() << "\"\n"; // ************************************************************************* // Delete metadata from the Exif data container // Delete the metadatum at iterator position pos key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities"); pos = exifData.findKey(key); if (pos == exifData.end()) throw Exiv2::Error("Key not found"); exifData.erase(pos); std::cout << "Deleted key \"" << key << "\"\n"; // ************************************************************************* // Finally, write the remaining Exif data to an image file int rc = exifData.write("img_2158.jpg"); if (rc) { std::string error = Exiv2::ExifData::strError(rc, "img_2158.jpg"); throw Exiv2::Error(error); } return 0; } catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; return -1; }
QgsPoint QgsExifTools::getGeoTag( const QString &imagePath, bool &ok ) { ok = false; if ( !QFileInfo::exists( imagePath ) ) return QgsPoint(); try { std::unique_ptr< Exiv2::Image > image( Exiv2::ImageFactory::open( imagePath.toStdString() ) ); if ( !image ) return QgsPoint(); image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if ( exifData.empty() ) return QgsPoint(); Exiv2::ExifData::iterator itLatRef = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSLatitudeRef" ) ); Exiv2::ExifData::iterator itLatVal = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSLatitude" ) ); Exiv2::ExifData::iterator itLonRef = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSLongitudeRef" ) ); Exiv2::ExifData::iterator itLonVal = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSLongitude" ) ); if ( itLatRef == exifData.end() || itLatVal == exifData.end() || itLonRef == exifData.end() || itLonVal == exifData.end() ) return QgsPoint(); auto readCoord = []( const QString & coord )->double { double res = 0; double div = 1; const QStringList parts = coord.split( QRegularExpression( QStringLiteral( "\\s+" ) ) ); for ( const QString &rational : parts ) { const QStringList pair = rational.split( '/' ); if ( pair.size() != 2 ) break; res += ( pair[0].toDouble() / pair[1].toDouble() ) / div; div *= 60; } return res; }; auto readRationale = []( const QString & rational )->double { const QStringList pair = rational.split( '/' ); if ( pair.size() != 2 ) return std::numeric_limits< double >::quiet_NaN(); return pair[0].toDouble() / pair[1].toDouble(); }; double lat = readCoord( QString::fromStdString( itLatVal->value().toString() ) ); double lon = readCoord( QString::fromStdString( itLonVal->value().toString() ) ); const QString latRef = QString::fromStdString( itLatRef->value().toString() ); const QString lonRef = QString::fromStdString( itLonRef->value().toString() ); if ( latRef.compare( QLatin1String( "S" ), Qt::CaseInsensitive ) == 0 ) { lat *= -1; } if ( lonRef.compare( QLatin1String( "W" ), Qt::CaseInsensitive ) == 0 ) { lon *= -1; } ok = true; Exiv2::ExifData::iterator itElevVal = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSAltitude" ) ); Exiv2::ExifData::iterator itElevRefVal = exifData.findKey( Exiv2::ExifKey( "Exif.GPSInfo.GPSAltitudeRef" ) ); if ( itElevVal != exifData.end() ) { double elev = readRationale( QString::fromStdString( itElevVal->value().toString() ) ); if ( itElevRefVal != exifData.end() ) { const QString elevRef = QString::fromStdString( itElevRefVal->value().toString() ); if ( elevRef.compare( QLatin1String( "1" ), Qt::CaseInsensitive ) == 0 ) { elev *= -1; } } return QgsPoint( lon, lat, elev ); } else { return QgsPoint( lon, lat ); } } catch ( ... ) { return QgsPoint(); } }