Sample usage of high-level metadata operations.

// SPDX-License-Identifier: GPL-2.0-or-later
// Sample program showing how to add, modify and delete Exif metadata.
#include <exiv2/exiv2.hpp>
#include <iostream>
int main(int argc, char* const argv[]) {
try {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " file\n";
std::string file(argv[1]);
// Container for exif metadata. This is an example of creating
// exif metadata from scratch. If you want to add, modify, delete
// metadata that exists in an image, start with ImageFactory::open
Exiv2::ExifData exifData;
// *************************************************************************
// Add to the Exif data
// This is the quickest way to add (simple) Exif data. If a metadatum for
// a given key already exists, its value is overwritten. Otherwise a new
// tag is added.
exifData["Exif.Image.Model"] = "Test 1"; // AsciiValue
exifData["Exif.Image.SamplesPerPixel"] = static_cast<uint16_t>(162); // UShortValue
exifData["Exif.Image.XResolution"] = -2; // LongValue
exifData["Exif.Image.YResolution"] = Exiv2::Rational(-2, 3); // RationalValue
std::cout << "Added a few tags the quick way.\n";
// Create a ASCII string value (note the use of create)
// 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.get());
std::cout << "Added key \"" << key << "\", value \"" << *v << "\"\n";
// Now create a more interesting value (without using the create method)
// Set two rational components from a string"1/2 1/3");
// Add more elements through the extended interface of rational value
rv.value_.emplace_back(2, 3);
rv.value_.emplace_back(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";
// *************************************************************************
// Modify Exif data
// Since we know that the metadatum exists (or we don't mind creating a new
// tag if it doesn't), we can simply do this:
Exiv2::Exifdatum& tag = exifData["Exif.Photo.DateTimeOriginal"];
std::string date = tag.toString();
date.replace(0, 4, "2000");
std::cout << "Modified key \"" << tag.key() << "\", new value \"" << tag.value() << "\"\n";
// Alternatively, we can use findKey()
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
auto pos = exifData.findKey(key);
if (pos == exifData.end())
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Key not found");
// Get a pointer to a copy of the value
v = pos->getValue();
// Downcast the Value pointer to its actual type
auto prv = dynamic_cast<Exiv2::URationalValue*>(v.get());
if (!prv)
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Downcast failed");
// Modify the value directly through the interface of URationalValue = {88, 77};
// Copy the modified value back to the metadatum
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(Exiv2::ErrorCode::kerErrorMessage, "Key not found");
std::cout << "Deleted key \"" << key << "\"\n";
// *************************************************************************
// Finally, write the remaining Exif data to the image file
auto image = Exiv2::ImageFactory::open(file);
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
static bool initialize(XmpParser::XmpLockFct xmpLockFct=nullptr, void *pLockData=nullptr)
Initialize the XMP Toolkit.
void add(const ExifKey &key, const Value *pValue)
Add an Exifdatum from the supplied key and value pair. This method copies (clones) key and value....
An Exif metadatum, consisting of an ExifKey and a Value and methods to manipulate these.
Definition: exif.hpp:41
std::pair< int32_t, int32_t > Rational
8 byte signed rational type.
Definition: types.hpp:31
std::string key() const override
Return the key of the Exifdatum.
ValueList value_
The container for all values. In your application, if you know what subclass of Value you're dealing ...
Definition: value.hpp:1214
@ asciiString
Exif ASCII type, 8-bit byte.
Definition: types.hpp:72
static Image::UniquePtr open(const std::string &path, bool useCurl=true)
Create an Image subclass of the appropriate type by reading the specified file. Image type is derived...
iterator end()
End of the metadata.
Definition: exif.hpp:433
ValueType< URational > URationalValue
Unsigned rational value type.
Definition: value.hpp:1302
Simple error class used for exceptions. An output operator is provided to print errors to a stream.
Definition: error.hpp:235
Concrete keys for Exif metadata and access to Exif tag reference data.
Definition: tags.hpp:271
int read(const byte *buf, size_t len, ByteOrder byteOrder) override
Read the value from a character buffer.
Definition: value.hpp:1502
static UniquePtr create(TypeId typeId)
A (simple) factory to create a Value type.
const Value & value() const override
Return a constant reference to the value.
static void terminate()
Terminate the XMP Toolkit and unregister custom namespaces.
iterator erase(iterator pos)
Delete the Exifdatum at iterator position pos, return the position of the next exifdatum....
std::string toString() const override
Return the value as a string.
@ date
IPTC date type.
Definition: types.hpp:88
iterator findKey(const ExifKey &key)
Find the first Exifdatum with the given key, return an iterator to it.
Template for a Value of a basic type. This is used for unsigned and signed short, long and rationals.
Definition: value.hpp:1131
A container for Exif data. This is a top-level class of the Exiv2 library. The container holds Exifda...
Definition: exif.hpp:373