fixed handling IPTC metadata that admit multiple values

(cherry picked from commit 8becb08ec1417215bf8f02c54000d37c2e6920f0)
This commit is contained in:
Alberto Griggio
2021-11-25 14:32:36 -08:00
committed by Lawrence Lee
parent a0e9a59606
commit b409e0bab2
4 changed files with 70 additions and 17 deletions

View File

@@ -81,6 +81,20 @@ std::unique_ptr<Exiv2::Image> open_exiv2(const Glib::ustring& fname,
return ret;
}
template <class Data, class Key>
void clear_metadata_key(Data &data, const Key &key)
{
while (true) {
auto it = data.findKey(key);
if (it == data.end()) {
break;
} else {
data.erase(it);
}
}
}
} // namespace
@@ -119,19 +133,30 @@ void Exiv2Metadata::load() const
if (!src_.empty() && !image_.get() && Glib::file_test(src_.c_str(), Glib::FILE_TEST_EXISTS)) {
CacheVal val;
auto finfo = Gio::File::create_for_path(src_)->query_info(G_FILE_ATTRIBUTE_TIME_MODIFIED);
if (cache_ && cache_->get(src_, val) && val.second >= finfo->modification_time()) {
image_ = val.first;
} else {
auto img = open_exiv2(src_, true);
image_.reset(img.release());
if (cache_) {
cache_->set(src_, CacheVal(image_, finfo->modification_time()));
Glib::TimeVal xmp_mtime(0, 0);
if (merge_xmp_) {
auto xmpname = xmpSidecarPath(src_);
if (Glib::file_test(xmpname.c_str(), Glib::FILE_TEST_EXISTS)) {
xmp_mtime = Gio::File::create_for_path(xmpname)->query_info(G_FILE_ATTRIBUTE_TIME_MODIFIED)->modification_time();
}
}
if (cache_ && cache_->get(src_, val) && val.image_mtime >= finfo->modification_time() && val.use_xmp == merge_xmp_ && val.xmp_mtime >= xmp_mtime) {
image_ = val.image;
} else {
auto img = open_exiv2(src_, true);
image_.reset(img.release());
if (merge_xmp_) {
do_merge_xmp(image_.get(), false);
}
if (cache_) {
val.image = image_;
val.image_mtime = finfo->modification_time();
val.xmp_mtime = xmp_mtime;
val.use_xmp = merge_xmp_;
cache_->set(src_, val);
}
}
}
}
@@ -198,7 +223,7 @@ void Exiv2Metadata::do_merge_xmp(Exiv2::Image *dst, bool keep_all) const
Exiv2::IptcData iptc;
Exiv2::copyXmpToIptc(xmp, iptc);
Exiv2::moveXmpToExif(xmp, exif);
std::unordered_set<std::string> seen;
std::unordered_map<std::string, std::unordered_set<std::string>> seen;
if (!keep_all) {
remove_unwanted(exif);
@@ -208,16 +233,23 @@ void Exiv2Metadata::do_merge_xmp(Exiv2::Image *dst, bool keep_all) const
dst->exifData()[datum.key()] = datum;
}
for (auto &datum : iptc) {
if (seen.insert(datum.key()).second) {
auto &s = seen[datum.key()];
if (s.empty()) {
clear_metadata_key(dst->iptcData(), Exiv2::IptcKey(datum.key()));
dst->iptcData()[datum.key()] = datum;
} else {
s.insert(datum.toString());
} else if (s.insert(datum.toString()).second) {
dst->iptcData().add(datum);
}
}
seen.clear();
for (auto &datum : xmp) {
if (seen.insert(datum.key()).second) {
auto &s = seen[datum.key()];
if (s.empty()) {
clear_metadata_key(dst->xmpData(), Exiv2::XmpKey(datum.key()));
dst->xmpData()[datum.key()] = datum;
} else {
s.insert(datum.toString());
} else if (s.insert(datum.toString()).second) {
dst->xmpData().add(datum);
}
}
@@ -415,9 +447,11 @@ void Exiv2Metadata::import_iptc_pairs(Exiv2::IptcData &out) const
try {
auto &v = p.second;
if (v.size() >= 1) {
out[p.first] = v[0];
for (size_t j = 1; j < v.size(); ++j) {
clear_metadata_key(out, Exiv2::IptcKey(p.first));
Exiv2::Iptcdatum d(Exiv2::IptcKey(p.first));
d.setValue(v[0]);
out[p.first] = d;
for (size_t j = 1; j < v.size(); ++j) {
d.setValue(v[j]);
out.add(d);
}

View File

@@ -85,7 +85,14 @@ private:
std::shared_ptr<std::unordered_set<std::string>> exif_keys_;
typedef std::pair<std::shared_ptr<Exiv2::Image>, Glib::TimeVal> CacheVal;
struct CacheVal {
std::shared_ptr<Exiv2::Image> image;
Glib::TimeVal image_mtime;
Glib::TimeVal xmp_mtime;
bool use_xmp;
CacheVal() = default;
};
//typedef std::pair<std::shared_ptr<Exiv2::Image>, Glib::TimeVal> CacheVal;
typedef Cache<Glib::ustring, CacheVal> ImageCache;
static std::unique_ptr<ImageCache> cache_;
};

View File

@@ -1803,6 +1803,11 @@ public:
return pairs.empty();
}
iterator erase(const const_iterator& key)
{
return pairs.erase(key);
}
void clear()
{
pairs.clear();

View File

@@ -673,6 +673,13 @@ void IPTCPanel::updateChangeList()
(*changeList)[DATE_CREATED].push_back(dateCreated->get_text());
(*changeList)[TRANS_REFERENCE].push_back(transReference->get_text());
for (auto &p : *embeddedData) {
auto it = changeList->find(p.first);
if (it != changeList->end() && p.second == it->second) {
changeList->erase(it);
}
}
notifyListener();
}