235{
236 ioDevice->open(QIODevice::ReadOnly);
238 std::string xmpPacket_;
239 QByteArray arr = ioDevice->readAll();
240 xmpPacket_.assign(arr.data(), arr.length());
242
243 Exiv2::XmpData xmpData_;
244 if (Exiv2::XmpParser::decode(xmpData_, xmpPacket_) != 0) {
246 return false;
247 }
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();
252
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") {
257
258
260 } else {
263 if (!schema) {
265 if (!schema) {
267 Q_ASSERT(schema);
268 }
269 }
270#if EXIV2_TEST_VERSION(0,28,0)
271 const Exiv2::Value::UniquePtr
value = it->getValue();
272#else
273 const Exiv2::Value::AutoPtr
value = it->getValue();
274#endif
275 QString structName;
276 int arrayIndex = -1;
277 QString tagName;
279
280 if (!
parseTagName(key.tagName().c_str(), structName, arrayIndex, tagName, &typeInfo, schema))
281 continue;
282
283 bool isStructureEntry = !structName.isEmpty() && arrayIndex == -1;
284 bool isStructureInArrayEntry = !structName.isEmpty() && arrayIndex != -1;
285 Q_ASSERT(isStructureEntry != isStructureInArrayEntry || !isStructureEntry);
286
288 bool ignoreValue = false;
289
290 if (
value->typeId() == Exiv2::xmpBag ||
value->typeId() == Exiv2::xmpSeq
291 ||
value->typeId() == Exiv2::xmpAlt) {
293 if (typeInfo) {
295 }
297 if (embeddedTypeInfo) {
298 parser = embeddedTypeInfo->
parser();
299 }
300 const Exiv2::XmpArrayValue *xav =
dynamic_cast<const Exiv2::XmpArrayValue *
>(
value.get());
301 Q_ASSERT(xav);
303#if EXIV2_TEST_VERSION(0,28,0)
304 for (size_t i = 0; i < xav->count(); ++i) {
305#else
306 for (int i = 0; i < xav->count(); ++i) {
307#endif
308 QString
value = QString::fromStdString(xav->toString(i));
309 if (parser) {
312 KisUsageLogger::log(QString(
"Cannot parse metadata value \"%1\" for %2. Assigning invalid value.").arg(
value, tagName));
313 }
314 array.push_back(parsed);
315
316 } else {
317 dbgImage <<
"No parser " << tagName;
319 }
320 }
322 switch (xav->xmpArrayType()) {
323 case Exiv2::XmpValue::xaNone:
324 warnKrita <<
"KisXMPIO: Unsupported array";
325 break;
326 case Exiv2::XmpValue::xaAlt:
328 break;
329 case Exiv2::XmpValue::xaBag:
331 break;
332 case Exiv2::XmpValue::xaSeq:
334 break;
335 }
337 }
else if (
value->typeId() == Exiv2::langAlt) {
338 const Exiv2::LangAltValue *xav =
dynamic_cast<const Exiv2::LangAltValue *
>(
value.get());
340
342 for (std::map<std::string, std::string>::const_iterator it = xav->value_.begin();
343 it != xav->value_.end();
344 ++it) {
347 alt.push_back(valt);
348 }
350 } else {
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));
356 }
357 } else {
360 }
361 if (valTxt == "type=\"Struct\"") {
363 ignoreValue = true;
364 }
365 }
366 }
367
368
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);
374 }
375
376 if (!arraysOfStructures[schema][structName][arrayIndex].contains(tagName)) {
377 arraysOfStructures[schema][structName][arrayIndex][tagName] =
v;
378 } else {
379 warnKrita <<
"WARNING: trying to overwrite tag" << tagName <<
"in" << structName << arrayIndex;
380 }
381 } else {
382 if (!ignoreValue) {
384 } else {
385 dbgMetaData <<
"Ignoring value for " << tagName <<
" " <<
v;
386 }
387 }
388 }
389 }
390
391 for (QMap<
const KisMetaData::Schema *, QMap<QString, QMap<QString, KisMetaData::Value>>>::iterator it =
392 structures.begin();
393 it != structures.end();
394 ++it) {
396 for (QMap<QString, QMap<QString, KisMetaData::Value>>::iterator it2 = it.value().begin();
397 it2 != it.value().end();
398 ++it2) {
400 }
401 }
403 arraysOfStructures.begin();
404 it != arraysOfStructures.end();
405 ++it) {
407 for (QMap<QString,
QVector<QMap<QString, KisMetaData::Value>>>::iterator it2 = it.value().begin();
408 it2 != it.value().end();
409 ++it2) {
411 QString entryName = it2.key();
416 break;
419 break;
422 break;
423 default:
425 break;
426 }
429 if (
value.isArray()) {
431 }
432 }
436 for (int i = 0; i < it2.value().size(); ++i) {
437 valueList.append(it2.value()[i]);
438 }
440 }
441 }
442 }
443
444 return true;
445}
float value(const T *src, size_t ch)
const KisMetaData::Value & value() const
static void log(const QString &message)
Logs with date/time.
BackendType type() const override
bool parseTagName(const QString &tagString, QString &structName, int &arrayIndex, QString &tagName, const KisMetaData::TypeInfo **typeInfo, const KisMetaData::Schema *schema)
int size(const Forest< T > &forest)