1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// SPDX-License-Identifier: GPL-2.0-or-later
#include <exiv2/exiv2.hpp>
#include <iostream>
// *****************************************************************************
// local declarations
using namespace Exiv2;
void testCase(const std::string& file1, const std::string& file2, const std::string& thumb, const std::string& key,
const std::string& value);
void exifPrint(const ExifData& exifData);
// *****************************************************************************
// Main
int main(int argc, char* const argv[]) {
Exiv2::XmpParser::initialize();
::atexit(Exiv2::XmpParser::terminate);
try {
if (argc != 3) {
std::cout << "Usage: write-test file case\n\n"
<< "where case is an integer between 1 and 11\n";
return EXIT_FAILURE;
}
std::string testFile = argv[1];
std::istringstream iss(argv[2]);
int testNo = 0;
iss >> testNo;
int rc = EXIT_SUCCESS;
switch (testNo) {
case 1:
std::cerr << "Case 1: ";
std::cerr << "Non-intrusive change to the standard Exif metadata\n";
testCase(testFile, "test1.jpg", "thumb1", "Exif.Photo.DateTimeOriginal", "1999:11:22 00:11:22");
break;
case 2:
std::cerr << "Case 2: ";
std::cerr << "Non-intrusive change to the makernote metadata\n";
testCase(testFile, "test2.jpg", "thumb2", "Exif.Canon.OwnerName", "Chan YeeSend");
break;
case 3:
std::cerr << "Case 3: ";
std::cerr << "Non-intrusive change to the Exif metadata (w/o makernote)\n";
testCase(testFile, "test3.jpg", "thumb3", "Exif.Photo.DateTimeOriginal", "1999:11:22 00:11:22");
break;
case 4:
std::cerr << "Case 4: ";
std::cerr << "Intrusive change to the standard Exif metadata\n";
testCase(testFile, "test4.jpg", "thumb4", "Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22 and twenty seconds");
break;
case 5:
std::cerr << "Case 5: ";
std::cerr << "Intrusive change to the Canon makernote metadata\n";
testCase(testFile, "test5.jpg", "thumb5", "Exif.Canon.OwnerName", "Frau Chan YeeSend und Herr Andreas Huggel");
break;
case 6:
std::cerr << "Case 6: ";
std::cerr << "Intrusive change to the Exif metadata (w/o makernote)\n";
testCase(testFile, "test6.jpg", "thumb6", "Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22 and twenty seconds");
break;
case 7:
std::cerr << "Case 7: ";
std::cerr << "Intrusive change to the Fujifilm makernote metadata\n";
testCase(testFile, "test7.jpg", "thumb7", "Exif.Fujifilm.Quality", "Typical Fujifilm Quality");
break;
case 8:
std::cerr << "Case 8: ";
std::cerr << "Intrusive change to the Sigma makernote metadata\n";
testCase(testFile, "test8.jpg", "thumb8", "Exif.Sigma.ResolutionMode", "Sigma HI resolution");
break;
case 9:
std::cerr << "Case 9: ";
std::cerr << "Intrusive change to the Nikon1 makernote metadata\n";
testCase(testFile, "test9.jpg", "thumb9", "Exif.Nikon1.Quality", "Typical Nikon1 Quality");
break;
case 10:
std::cerr << "Case 10: ";
std::cerr << "Intrusive change to the Nikon2 makernote metadata\n";
testCase(testFile, "test10.jpg", "thumb10", "Exif.Nikon2.0x0002", "Nikon2 Version 2");
break;
case 11:
std::cerr << "Case 11: ";
std::cerr << "Intrusive change to the Nikon3 makernote metadata\n";
testCase(testFile, "test11.jpg", "thumb11", "Exif.Nikon3.Quality", "Typical Nikon3 Quality");
break;
// ToDo: Erase Sigma thumbnail
// ToDo: Write to a broken (truncated) IFD entry
default:
std::cout << "Usage: exiftest file case\n\n"
<< "where case is an integer between 1 and 11\n";
rc = EXIT_FAILURE;
break;
}
return rc;
} catch (Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return EXIT_FAILURE;
}
}
// *****************************************************************************
void testCase(const std::string& file1, const std::string& file2, const std::string& thumb, const std::string& key,
const std::string& value) {
ExifKey ek(key);
// Open first image
auto image1 = ImageFactory::open(file1);
// Load existing metadata
std::cerr << "---> Reading file " << file1 << "\n";
image1->readMetadata();
Exiv2::ExifData& ed1 = image1->exifData();
std::cerr << "---> Modifying Exif data\n";
auto pos = ed1.findKey(ek);
if (pos == ed1.end()) {
throw Error(ErrorCode::kerErrorMessage, "Metadatum with key = " + ek.key() + " not found");
}
pos->setValue(value);
// Open second image
auto image2 = ImageFactory::open(file2);
image2->setExifData(image1->exifData());
std::cerr << "---> Writing Exif data to file " << file2 << "\n";
image2->writeMetadata();
std::cerr << "---> Reading file " << file2 << "\n";
image2->readMetadata();
Exiv2::ExifData& ed2 = image2->exifData();
exifPrint(ed2);
std::cerr << "---> Writing Exif thumbnail to file " << thumb << ".*\n";
ExifThumbC et2(ed2);
auto s = et2.writeFile(thumb);
if (s == 0)
std::cerr << "---> Failed to write to file " << thumb << ".*\n";
}
// *****************************************************************************
void exifPrint(const ExifData& exifData) {
auto i = exifData.begin();
for (; i != exifData.end(); ++i) {
std::cout << std::setw(44) << std::setfill(' ') << std::left << i->key() << " "
<< "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9)
<< std::setfill(' ') << std::left << i->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ')
<< std::right << i->count() << " " << std::dec << i->value() << "\n";
}
}
|