Exiv2 is an open-source C++ library and command-line tool dedicated to handling image metadata. It enables reading, writing, deleting, and modifying metadata formats such as Exif, IPTC, XMP, and ICC profiles embedded in image files. With its extensive API, Exiv2 is ideal for image-processing software development and supports version control as well as privacy considerations. Its extensible design allows it to accommodate future metadata standards.
The library supports metadata operations on a wide range of image formats, including JPEG, TIFF, PNG, and others. Beyond basic read/write capabilities, Exiv2 offers advanced features such as adding, removing, querying, converting metadata, and performing certain image edits.
Understanding Exif
Exif (Exchangeable Image File Format) is a standard for storing metadata within digital camera images. Originaly proposed by the Japan Electronic Industry Development Association (JEIDA) in 1995, Exif captures detailed shooting information like date, time, camera model, exposure, aperture, ISO, flash usage, and more. It also supports thumbnail previews and raw data storage.
Exif extends the JPEG and TIFF formats by embedding additional attribute metadata alongside image data. This metadata is crucial for photographers and editors because it provides environmental and technical context, aiding image quality evaluation and technique improvement.
Reading and Writing Exif Data
Reading and writing Exif data is a core capability of Exiv2. The library can effortlessly extract Exif information from JPEG or TIFF files. Writing Exif data typically occurs after image capture to modify or add fields.
Below is an example of reading Exif metadata from a JPEG file using Exiv2:
#include <exiv2/exiv2.hpp>
#include <iostream>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("sample.jpg");
img->readMetadata();
const Exiv2::ExifData& exifData = img->exifData();
for (auto it = exifData.begin(); it != exifData.end(); ++it) {
std::cout << it->key() << "\n " << it->value() << std::endl;
}
return 0;
}
To modify Exif data, the library provides straightforward assignment operators. For instance, you can update the capture timestamp or add a descripsion:
#include <exiv2/exiv2.hpp>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("sample.jpg");
img->readMetadata();
Exiv2::ExifData& exifData = img->exifData();
// Update date and time
exifData["Exif.Photo.DateTime"] = "2023:04:11 10:59:58";
// Add image description
exifData["Exif.Image.ImageDescription"] = "A serene sunset";
img->writeMetadata();
return 0;
}
When privacy is a concern, you might need to delete specific Exif fields. The library simplifies this:
#include <exiv2/exiv2.hpp>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("sample.jpg");
img->readMetadata();
// Remove date/time information
img->exifData()["Exif.Photo.DateTime"].clear();
// Alternatively, use erase: img->exifData().erase(img->exifData().findKey(Exiv2::ExifKey("Exif.Photo.DateTime")));
img->writeMetadata();
return 0;
}
Working with IPTC Data
Reading and editing IPTC metadata follows a pattern similar to Exif. The code below demonstrates how to retrieve and set IPTC fields:
#include <exiv2/exiv2.hpp>
#include <iostream>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("sample.jpg");
img->readMetadata();
Exiv2::IptcData& iptcData = img->iptcData();
// Display current IPTC entries
for (auto it = iptcData.begin(); it != iptcData.end(); ++it) {
std::cout << it->key() << "\n " << it->value() << std::endl;
}
// Set new values
iptcData["Iptc.Application2.Byline"] = "Jane Smith";
iptcData["Iptc.Application2.Caption"] = "Photo of a coastal sunset";
img->writeMetadata();
return 0;
}
Inserting and Extracting XMP Data
XMP (Extensible Metadata Platform) support in Exiv2 allows you to read and write XML-based metadata. Here is how to manipulate XMP data:
#include <exiv2/exiv2.hpp>
#include <iostream>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("sample.jpg");
img->readMetadata();
Exiv2::XmpData& xmpData = img->xmpData();
// Print existing XMP entries
for (auto it = xmpData.begin(); it != xmpData.end(); ++it) {
std::cout << it->key() << "\n " << it->value() << std::endl;
}
// Add Dublin Core fields
xmpData["Xmp.dc.title"] = "Sunset View";
xmpData["Xmp.dc.description"] = "Example of XMP metadata usage";
img->writeMetadata();
return 0;
}
ICC Profile Handling
Exiv2 also supports reading and writing embedded ICC color profiles. The following code opens an image with an ICC profile, retrieves profile metadata, and then writes the same profile into a new file:
#include <exiv2/exiv2.hpp>
#include <iostream>
int main() {
Exiv2::Image::AutoPtr img = Exiv2::ImageFactory::open("image_with_icc.jpg");
if (!img) {
std::cerr << "Cannot open image." << std::endl;
return -1;
}
Exiv2::ICCProfile::AutoPtr icc = img->iccProfile();
if (!icc) {
std::cerr << "No ICC profile found." << std::endl;
return -1;
}
std::cout << "Profile size: " << icc->size() << " bytes\n"
<< "Profile version: " << icc->version() << std::endl;
// Write ICC profile to another image
Exiv2::Image::AutoPtr outImg = Exiv2::ImageFactory::open("output_with_icc.jpg");
outImg->setIccProfile(icc);
outImg->writeFile();
return 0;
}
In this example, open() loads the source image, iccProfile() retrieves the profile, and size() and version() provide metadata about the profile. The extracted profile is then embedded into a new image using setIccProfile() and saved with writeFile().