73 Exiv2::XmpData xmpData_;
84 QMap<QString, KisMetaData::Value> structure =
value.asStructure();
89 if (!structureSchema) {
90 dbgMetaData <<
"Unknown schema for " << entry.name();
91 structureSchema = entry.schema();
93 Q_ASSERT(structureSchema);
94 saveStructure(xmpData_, entry.name(), prefix, structure, structureSchema);
96 Exiv2::XmpKey key(prefix, entry.name().toLatin1().constData());
103 Exiv2::XmpTextValue tv;
106 tv.setXmpArrayType(Exiv2::XmpValue::xaSeq);
109 tv.setXmpArrayType(Exiv2::XmpValue::xaBag);
112 tv.setXmpArrayType(Exiv2::XmpValue::xaAlt);
118 xmpData_.add(key, &tv);
121 if (structureTypeInfo) {
124 if (!structureSchema) {
125 dbgMetaData <<
"Unknown schema for " << entry.name();
126 structureSchema = entry.schema();
128 Q_ASSERT(structureSchema);
130 for (
int idx = 0; idx < array.size(); ++idx) {
131 saveStructure(xmpData_,
132 QString(
"%1[%2]").arg(entry.name()).arg(idx + 1),
134 array[idx].asStructure(),
140 if (
v &&
v->typeId() != Exiv2::TypeId::invalidTypeId) {
141 xmpData_.add(key,
v);
144 KisUsageLogger::log(QString(
"Invalid metadata value \"%1\" for key %2. The metadata key is therefore skipped during saving.").arg(
value.toString(), entry.name()));
151 std::string xmpPacket_;
153 Exiv2::XmpParser::encode(xmpPacket_, xmpData_);
154 }
catch (std::exception &e) {
155 warnMetaData <<
"Couldn't encode the data, error =" << e.what();
159 ioDevice->open(QIODevice::WriteOnly);
161 xmpPacket_ =
"http://ns.adobe.com/xap/1.0/\0" + xmpPacket_;
163 ioDevice->write(xmpPacket_.c_str(), xmpPacket_.length());
177 int numSubNames = tagString.count(
'/') + 1;
179 if (numSubNames == 1) {
186 if (numSubNames == 2) {
191 QRegularExpression regexp(
"([A-Za-z]\\w+)/([A-Za-z]\\w+):([A-Za-z]\\w+)");
192 regexp.setPatternOptions(QRegularExpression::UseUnicodePropertiesOption);
194 QRegularExpressionMatch match;
195 if (tagString.contains(regexp, &match)) {
196 structName = match.captured(1);
197 tagName = match.captured(3);
207 QRegularExpression regexp2(
"([A-Za-z]\\w+)\\[(\\d+)\\]/([A-Za-z]\\w+):([A-Za-z]\\w+)");
208 regexp2.setPatternOptions(QRegularExpression::UseUnicodePropertiesOption);
210 QRegularExpressionMatch match2;
211 if (tagString.contains(regexp2, &match2)) {
212 structName = match2.captured(1);
213 arrayIndex = match2.captured(2).toInt() - 1;
214 tagName = match2.captured(4);
229 warnKrita <<
"WARNING: Unsupported tag. We do not yet support nested tags. The tag will be dropped!";
230 warnKrita <<
" Failing tag:" << tagString;
236 ioDevice->open(QIODevice::ReadOnly);
238 std::string xmpPacket_;
239 QByteArray arr = ioDevice->readAll();
240 xmpPacket_.assign(arr.data(), arr.length());
243 Exiv2::XmpData xmpData_;
244 if (Exiv2::XmpParser::decode(xmpData_, xmpPacket_) != 0) {
248 QMap<const KisMetaData::Schema *, QMap<QString, QMap<QString, KisMetaData::Value>>> structures;
249 QMap<const KisMetaData::Schema *, QMap<QString, QVector<QMap<QString, KisMetaData::Value>>>> arraysOfStructures;
250 for (Exiv2::XmpData::iterator it = xmpData_.begin(); it != xmpData_.end(); ++it) {
251 dbgMetaData <<
"Start iteration" << it->key().c_str();
253 Exiv2::XmpKey key(it->key());
254 dbgMetaData << key.groupName().c_str() <<
" " << key.tagName().c_str() <<
" " << key.ns().c_str();
255 if ((key.groupName() ==
"exif" || key.groupName() ==
"tiff")
256 && key.tagName() ==
"NativeDigest") {
270#if EXIV2_TEST_VERSION(0,28,0)
271 const Exiv2::Value::UniquePtr
value = it->getValue();
273 const Exiv2::Value::AutoPtr
value = it->getValue();
280 if (!
parseTagName(key.tagName().c_str(), structName, arrayIndex, tagName, &typeInfo, schema))
283 bool isStructureEntry = !structName.isEmpty() && arrayIndex == -1;
284 bool isStructureInArrayEntry = !structName.isEmpty() && arrayIndex != -1;
285 Q_ASSERT(isStructureEntry != isStructureInArrayEntry || !isStructureEntry);
288 bool ignoreValue =
false;
290 if (
value->typeId() == Exiv2::xmpBag ||
value->typeId() == Exiv2::xmpSeq
291 ||
value->typeId() == Exiv2::xmpAlt) {
297 if (embeddedTypeInfo) {
298 parser = embeddedTypeInfo->
parser();
300 const Exiv2::XmpArrayValue *xav =
dynamic_cast<const Exiv2::XmpArrayValue *
>(
value.get());
303#if EXIV2_TEST_VERSION(0,28,0)
304 for (
size_t i = 0; i < xav->count(); ++i) {
306 for (
int i = 0; i < xav->count(); ++i) {
308 QString
value = QString::fromStdString(xav->toString(i));
312 KisUsageLogger::log(QString(
"Cannot parse metadata value \"%1\" for %2. Assigning invalid value.").arg(
value, tagName));
314 array.push_back(parsed);
317 dbgImage <<
"No parser " << tagName;
322 switch (xav->xmpArrayType()) {
323 case Exiv2::XmpValue::xaNone:
324 warnKrita <<
"KisXMPIO: Unsupported array";
326 case Exiv2::XmpValue::xaAlt:
329 case Exiv2::XmpValue::xaBag:
332 case Exiv2::XmpValue::xaSeq:
337 }
else if (
value->typeId() == Exiv2::langAlt) {
338 const Exiv2::LangAltValue *xav =
dynamic_cast<const Exiv2::LangAltValue *
>(
value.get());
342 for (std::map<std::string, std::string>::const_iterator it = xav->value_.begin();
343 it != xav->value_.end();
351 QString valTxt =
value->toString().c_str();
352 if (typeInfo && typeInfo->
parser()) {
355 KisUsageLogger::log(QString(
"Cannot parse metadata value \"%1\" for %2. Assigning invalid value.").arg(valTxt, tagName));
361 if (valTxt ==
"type=\"Struct\"") {
369 if (isStructureEntry) {
370 structures[schema][structName][tagName] =
v;
371 }
else if (isStructureInArrayEntry) {
372 if (arraysOfStructures[schema][structName].size() <= arrayIndex) {
373 arraysOfStructures[schema][structName].resize(arrayIndex + 1);
376 if (!arraysOfStructures[schema][structName][arrayIndex].contains(tagName)) {
377 arraysOfStructures[schema][structName][arrayIndex][tagName] =
v;
379 warnKrita <<
"WARNING: trying to overwrite tag" << tagName <<
"in" << structName << arrayIndex;
385 dbgMetaData <<
"Ignoring value for " << tagName <<
" " <<
v;
391 for (QMap<
const KisMetaData::Schema *, QMap<QString, QMap<QString, KisMetaData::Value>>>::iterator it =
393 it != structures.end();
396 for (QMap<QString, QMap<QString, KisMetaData::Value>>::iterator it2 = it.value().begin();
397 it2 != it.value().end();
403 arraysOfStructures.begin();
404 it != arraysOfStructures.end();
407 for (QMap<QString,
QVector<QMap<QString, KisMetaData::Value>>>::iterator it2 = it.value().begin();
408 it2 != it.value().end();
411 QString entryName = it2.key();
429 if (
value.isArray()) {
436 for (
int i = 0; i < it2.value().size(); ++i) {
437 valueList.append(it2.value()[i]);
bool parseTagName(const QString &tagString, QString &structName, int &arrayIndex, QString &tagName, const KisMetaData::TypeInfo **typeInfo, const KisMetaData::Schema *schema)