From 821144511d3734abe8fc447d18e89c15671c4c49 Mon Sep 17 00:00:00 2001 From: Daniel Sabelnikov Date: Sun, 28 Jun 2015 15:08:53 +0300 Subject: [PATCH] Support multiple values with Array --- exiv2node.cc | 87 +++++++++++++++++++++++++++++++++--------- test/images/books.jpg | Bin 993738 -> 993794 bytes test/test.js | 10 +++++ 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/exiv2node.cc b/exiv2node.cc index 7d4c21d..8df82d9 100644 --- a/exiv2node.cc +++ b/exiv2node.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,7 @@ using namespace v8; // Create a map of strings for passing them back and forth between the V8 and // worker threads. -typedef std::map tag_map_t; +typedef std::map > tag_map_t; class Exiv2Worker : public NanAsyncWorker { public: @@ -51,7 +52,7 @@ class GetTagsWorker : public Exiv2Worker { if (exifData.empty() == false) { Exiv2::ExifData::const_iterator end = exifData.end(); for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { - tags.insert(std::pair (i->key(), i->value().toString())); + tags[i->key()].push_back(i->value().toString()); } } @@ -59,7 +60,7 @@ class GetTagsWorker : public Exiv2Worker { if (iptcData.empty() == false) { Exiv2::IptcData::const_iterator end = iptcData.end(); for (Exiv2::IptcData::const_iterator i = iptcData.begin(); i != end; ++i) { - tags.insert(std::pair (i->key(), i->value().toString())); + tags[i->key()].push_back(i->value().toString()); } } @@ -67,7 +68,7 @@ class GetTagsWorker : public Exiv2Worker { if (xmpData.empty() == false) { Exiv2::XmpData::const_iterator end = xmpData.end(); for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i) { - tags.insert(std::pair (i->key(), i->value().toString())); + tags[i->key()].push_back(i->value().toString()); } } } catch (std::exception& e) { @@ -88,7 +89,19 @@ class GetTagsWorker : public Exiv2Worker { Local hash = NanNew(); // Copy the tags out. for (tag_map_t::iterator i = tags.begin(); i != tags.end(); ++i) { - hash->Set(NanNew(i->first.c_str()), NanNew(i->second.c_str())); + std::list &value = i->second; + if (value.size() > 1) { + // insert array + Local list = NanNew(value.size()); + uint32_t index = 0; + for (std::list::iterator j = value.begin(); j != value.end(); j++) { + list->Set(index++, NanNew(j->c_str())); + } + hash->Set(NanNew(i->first.c_str()), list); + } else { + // insert string + hash->Set(NanNew(i->first.c_str()), NanNew(value.front().c_str())); + } } argv[1] = hash; } @@ -135,16 +148,52 @@ class SetTagsWorker : public Exiv2Worker { Exiv2::IptcData &iptcData = image->iptcData(); Exiv2::XmpData &xmpData = image->xmpData(); + exifData.sortByKey(); + iptcData.sortByKey(); + xmpData.sortByKey(); + // Assign the tags. for (tag_map_t::iterator i = tags.begin(); i != tags.end(); ++i) { - if (i->first.compare(0, 5, "Exif.") == 0) { - exifData[i->first].setValue(i->second); - } else if (i->first.compare(0, 5, "Iptc.") == 0) { - iptcData[i->first].setValue(i->second); - } else if (i->first.compare(0, 4, "Xmp.") == 0) { - xmpData[i->first].setValue(i->second); + const std::string &key = i->first; + std::list &val = i->second; + if (val.size() > 1) { + // multiple entries, replace all matching properties + if (key.compare(0, 5, "Exif.") == 0) { + Exiv2::ExifData::iterator it = exifData.findKey(Exiv2::ExifKey(key)); + while (it != exifData.end() && it->key() == key) it = exifData.erase(it); + Exiv2::AsciiValue exivValue; + for (std::list::iterator l = val.begin(); l != val.end(); l++) { + exivValue.read(*l); + exifData.add(Exiv2::ExifKey(key), &exivValue); + } + } else if (key.compare(0, 5, "Iptc.") == 0) { + Exiv2::IptcData::iterator it = iptcData.findKey(Exiv2::IptcKey(key)); + while (it != iptcData.end() && it->key() == key) it = iptcData.erase(it); + Exiv2::AsciiValue exivValue; + for (std::list::iterator l = val.begin(); l != val.end(); l++) { + exivValue.read(*l); + iptcData.add(Exiv2::IptcKey(key), &exivValue); + } + iptcData[key].setValue(val.front()); + } else if (key.compare(0, 4, "Xmp.") == 0) { + Exiv2::XmpData::iterator it = xmpData.findKey(Exiv2::XmpKey(key)); + while (it != xmpData.end() && it->key() == key) it = xmpData.erase(it); + Exiv2::AsciiValue exivValue; + for (std::list::iterator l = val.begin(); l != val.end(); l++) { + exivValue.read(*l); + xmpData.add(Exiv2::XmpKey(key), &exivValue); + } + } } else { - //std::cerr << "skipping unknown tag " << i->first << std::endl; + if (key.compare(0, 5, "Exif.") == 0) { + exifData[key].setValue(val.front()); + } else if (key.compare(0, 5, "Iptc.") == 0) { + iptcData[key].setValue(val.front()); + } else if (key.compare(0, 4, "Xmp.") == 0) { + xmpData[key].setValue(val.front()); + } else { + //std::cerr << "skipping unknown tag " << key << std::endl; + } } } @@ -189,11 +238,15 @@ NAN_METHOD(SetImageTags) { Local tags = Local::Cast(args[1]); Local keys = tags->GetPropertyNames(); for (unsigned i = 0; i < keys->Length(); i++) { - Handle key = keys->Get(i); - worker->tags.insert(std::pair ( - *NanUtf8String(key), - *NanUtf8String(tags->Get(key))) - ); + Handle key = keys->Get(i); + if (tags->Get(key)->IsArray()) { + Handle array = Handle::Cast(tags->Get(key)); + for (unsigned i = 0; i < array->Length(); i++) { + worker->tags[*NanUtf8String(key)].push_back(*NanUtf8String(array->Get(i))); + } + } else { + worker->tags[*NanUtf8String(key)].push_back(*NanUtf8String(tags->Get(key))); + } } NanAsyncQueueWorker(worker); diff --git a/test/images/books.jpg b/test/images/books.jpg index 32dea95746e813deb8cb268af9ab723c8448edba..809ccccbbadba5cd0966ee699ceec6a9c684a134 100644 GIT binary patch delta 137 zcmX?g*{11=&4xNg#-7dfj4cZ0ZyC%2GV)9Ei!<^I6pZx@7%ZGTeOXu-KtM`{Ns@s% zKQ9$bmz3v&Xx5U9qSVx8CZ%>JB}O1-0%B$$W&vVWAZ7z%b|B^eVoo6D0%C3;<^f_} NAm-c7q{M%M9RR_{ABO+{ delta 81 zcmZp=Vsq-U&4xNg#wnZY8Cw*Zt(DrXl^B7T35c12m<5PgftU@5*@2h?h&h3n3y8Ua Rm