From 2313c6ad74471aa36c48b8a273ed9cde56a6c256 Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Mon, 10 May 2004 13:16:19 +0000 Subject: [PATCH] Added exifcomment sample program --- src/exifcomment.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 src/exifcomment.cpp diff --git a/src/exifcomment.cpp b/src/exifcomment.cpp new file mode 100644 index 00000000..45ed8abe --- /dev/null +++ b/src/exifcomment.cpp @@ -0,0 +1,162 @@ +// ***************************************************************** -*- C++ -*- +/* + Abstract : Sample program showing how to set the Exif comment of an image + + File: exifcomment.cpp + Version : $Name: $ $Revision: 1.1 $ + Author(s): Andreas Huggel (ahu) + History : 10-May-04, ahu: created + */ +// ***************************************************************************** +// included header files +#include "exif.hpp" +#include +#include +#include + +// ***************************************************************************** +// local declarations + +std::string readError(int rc, const std::string& path); +std::string writeError(int rc, const std::string& path); + +// ***************************************************************************** +// Main +int main(int argc, char* const argv[]) +try { + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " file\n"; + return 1; + } + + Exiv2::ExifData exifData; + int rc = exifData.read(argv[1]); + if (rc) { + std::string error = readError(rc, argv[1]); + throw Exiv2::Error(error); + } + + /* + There are two pitfalls that we need to consider when setting the Exif user + comment (Image.UserInfo.UserComment) of an image: + + First, the type of the Exif user comment tag is "undefined" (and not + ASCII) according to the Exif standard. This means that in Exiv2, we have + to deal with a DataValue (and not an AsciiValue). DataValue has the usual + two read methods, however, the one taking a const std::string& buf expects + the string to contain a series of integers (e.g., "0 1 2") and not a text + string. Thus, we need to use the read function that reads the value from a + character buffer of a given length. + + Second, the Exif comment field starts with an eight character area that + identifies the used character set. For ASCII, these eight characters are + "ASCII\0\0\0". The actual comment follows after this code. + + Note: There is a more simple Exif tag for the title of an image. It is a + 20 byte string (type ASCII) and does not store two-byte characters. + (Image.OtherTags.ImageDescription) + */ + + // Initialise a data value with the character set and comment + std::string charset("ASCII\0\0\0", 8); + std::string comment("A comment added to the Exif metadata through Exiv2"); + Exiv2::DataValue value; + value.read((charset + comment).data(), 8 + comment.size()); + + // Set the Exif comment + std::string key = "Image.UserInfo.UserComment"; + Exiv2::ExifData::iterator pos = exifData.findKey(key); + if (pos != exifData.end()) { + // Use the existing Exif UserComment metadatum if there is one + pos->setValue(&value); + } + else { + // Otherwise add a new UserComment metadatum + exifData.add(key, &value); + pos = exifData.findKey(key); + } + + // Now we should have a valid iterator in any case. We use the metadatum + // output operator to print the formatted value + std::cout << "Writing user comment '" << *pos << "' back to the image\n"; + + rc = exifData.write(argv[1]); + if (rc) { + std::string error = writeError(rc, argv[1]); + throw Exiv2::Error(error); + } + + return rc; +} +catch (Exiv2::Error& e) { + std::cout << "Caught Exiv2 exception '" << e << "'\n"; + return -1; +} + +// ***************************************************************************** +// local definitions + +std::string readError(int rc, const std::string& path) +{ + std::string error; + switch (rc) { + case -1: + error = path + ": Failed to open the file"; + break; + case -2: + error = path + ": The file contains data of an unknown image type"; + break; + case 1: + error = path + ": Couldn't read from the input stream"; + break; + case 2: + error = path + ": This does not look like a JPEG image"; + break; + case 3: + error = path + ": No Exif data found in the file"; + break; + case -99: + error = path + ": Unsupported Exif or GPS data found in IFD 1"; + break; + default: + error = path + ": Reading Exif data failed, rc = " + Exiv2::toString(rc); + break; + } + return error; +} // exifReadError + +std::string writeError(int rc, const std::string& path) +{ + std::string error; + switch (rc) { + case -1: + error = path + ": Failed to open the file"; + break; + case -2: + error = path + ": The file contains data of an unknown image type"; + break; + case -3: + error = path + ": Couldn't open temporary file"; + break; + case -4: + error = path + ": Renaming temporary file failed"; + break; + case 1: + error = path + ": Couldn't read from the input stream"; + break; + case 2: + error = path + ": This does not look like a JPEG image"; + break; + case 3: + error = path + ": No JFIF APP0 or Exif APP1 segment found in the file"; + break; + case 4: + error = path + ": Writing to the output stream failed"; + break; + default: + error = path + ": Reading Exif data failed, rc = " + Exiv2::toString(rc); + break; + } + return error; +} // writeError