-
Notifications
You must be signed in to change notification settings - Fork 284
/
Copy pathmetacopy.cpp
167 lines (152 loc) · 4.29 KB
/
metacopy.cpp
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
164
165
166
167
// SPDX-License-Identifier: GPL-2.0-or-later
#include <exiv2/exiv2.hpp>
// include local header files which are not part of libexiv2
#include "metacopy.hpp"
// *****************************************************************************
// Main
int main(int argc, char* const argv[]) {
try {
Exiv2::XmpParser::initialize();
::atexit(Exiv2::XmpParser::terminate);
// Handle command line arguments
Params params;
if (params.getopt(argc, argv)) {
params.usage();
return 1;
}
if (params.help_) {
params.help();
return 2;
}
// Use MemIo to increase test coverage.
Exiv2::FileIo fileIo(params.read_);
auto memIo = std::make_unique<Exiv2::MemIo>();
memIo->transfer(fileIo);
auto readImg = Exiv2::ImageFactory::open(std::move(memIo));
readImg->readMetadata();
auto writeImg = Exiv2::ImageFactory::open(params.write_);
if (params.preserve_) {
writeImg->readMetadata();
}
if (params.iptc_) {
writeImg->setIptcData(readImg->iptcData());
}
if (params.exif_) {
writeImg->setExifData(readImg->exifData());
}
if (params.comment_) {
writeImg->setComment(readImg->comment());
}
if (params.xmp_) {
writeImg->setXmpData(readImg->xmpData());
}
try {
writeImg->writeMetadata();
} catch (const Exiv2::Error&) {
std::cerr << params.progname() << ": Could not write metadata to (" << params.write_ << ")\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} catch (Exiv2::Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return EXIT_FAILURE;
}
}
int Params::option(int opt, const std::string& /*optarg*/, int optopt) {
int rc = 0;
switch (opt) {
case 'h': {
help_ = true;
break;
}
case 'i': {
iptc_ = true;
break;
}
case 'e': {
exif_ = true;
break;
}
case 'c': {
comment_ = true;
break;
}
case 'x': {
xmp_ = true;
break;
}
case 'p': {
preserve_ = true;
break;
}
case 'a': {
iptc_ = true;
exif_ = true;
comment_ = true;
xmp_ = true;
break;
}
case ':': {
std::cerr << progname() << ": Option -" << static_cast<char>(optopt) << " requires an argument\n";
rc = 1;
break;
}
case '?': {
std::cerr << progname() << ": Unrecognized option -" << static_cast<char>(optopt) << "\n";
rc = 1;
break;
}
default: {
std::cerr << progname() << ": getopt returned unexpected character code " << std::hex << opt << "\n";
rc = 1;
break;
}
}
return rc;
}
int Params::nonoption(const std::string& argv) {
if (!write_.empty()) {
std::cerr << progname() << ": Unexpected extra argument (" << argv << ")\n";
return 1;
}
if (first_)
read_ = argv;
else
write_ = argv;
first_ = false;
return 0;
}
int Params::getopt(int argc, char* const argv[]) {
int rc = Util::Getopt::getopt(argc, argv, optstring_);
// Further consistency checks
if (!help_) {
if (rc == 0 && read_.empty()) {
std::cerr << progname() << ": Read and write files must be specified\n";
rc = 1;
}
if (rc == 0 && write_.empty()) {
std::cerr << progname() << ": Write file must be specified\n";
rc = 1;
}
if (preserve_ && iptc_ && exif_ && comment_ && xmp_) {
std::cerr << progname() << ": Option -p has no effect when all metadata types are specified.\n";
rc = 1;
}
}
return rc;
} // Params::getopt
void Params::usage(std::ostream& os) const {
os << "\nReads and writes raw metadata. Use -h option for help.\n"
<< "Usage: " << progname() << " [-iecxaph] readfile writefile\n";
}
void Params::help(std::ostream& os) const {
usage(os);
os << "\nOptions:\n"
<< " -i Read Iptc data from readfile and write to writefile.\n"
<< " -e Read Exif data from readfile and write to writefile.\n"
<< " -c Read Jpeg comment from readfile and write to writefile.\n"
<< " -x Read XMP data from readfile and write to writefile.\n"
<< " -a Read all metadata from readfile and write to writefile.\n"
<< " -p Preserve existing metadata in writefile if not replaced.\n"
<< " -h Display this help and exit.\n\n";
} // Params::help