// SPDX-License-Identifier: GPL-2.0-or-later #include #include // ***************************************************************************** // 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); #ifdef EXV_ENABLE_BMFF Exiv2::enableBMFF(); #endif 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"; } }