Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_exiv2_common.h File Reference
#include <exiv2/exiv2.hpp>
#include <QDateTime>
#include <QScopedPointer>
#include <kis_debug.h>
#include <kis_meta_data_value.h>

Go to the source code of this file.

Functions

template<typename T >
Exiv2::Value * arrayToExivValue (const KisMetaData::Value &value)
 
KisMetaData::Value exivValueToKMDValue (const Exiv2::Value::AutoPtr &value, bool forceSeq, KisMetaData::Value::ValueType arrayType=KisMetaData::Value::UnorderedArray)
 
Exiv2::Value * kmdValueToExivValue (const KisMetaData::Value &value, Exiv2::TypeId type)
 Convert a KisMetaData to an Exiv value.
 
Exiv2::Value * kmdValueToExivXmpValue (const KisMetaData::Value &value)
 
Exiv2::Value * variantToExivValue (const QVariant &variant, Exiv2::TypeId type)
 

Function Documentation

◆ arrayToExivValue()

template<typename T >
Exiv2::Value * arrayToExivValue ( const KisMetaData::Value & value)

Definition at line 168 of file kis_exiv2_common.h.

169{
170 Exiv2::ValueType<T> *exivValue = new Exiv2::ValueType<T>();
171 const QList<KisMetaData::Value> array = value.asArray();
172 Q_FOREACH (const KisMetaData::Value &item, array) {
173 exivValue->value_.push_back(qvariant_cast<T>(item.asVariant()));
174 }
175 return exivValue;
176}
float value(const T *src, size_t ch)
QVariant asVariant() const

References KisMetaData::Value::asVariant(), and value().

◆ exivValueToKMDValue()

KisMetaData::Value exivValueToKMDValue ( const Exiv2::Value::AutoPtr & value,
bool forceSeq,
KisMetaData::Value::ValueType arrayType = KisMetaData::Value::UnorderedArray )
inline

Definition at line 26 of file kis_exiv2_common.h.

28{
29 switch (value->typeId()) {
30 case Exiv2::signedByte:
31 case Exiv2::invalidTypeId:
32 case Exiv2::lastTypeId:
33 case Exiv2::directory:
34 dbgMetaData << "Invalid value :" << value->typeId() << " value =" << value->toString().c_str();
35 return {};
36 case Exiv2::undefined: {
37 dbgMetaData << "Undefined value :" << value->typeId() << " value =" << value->toString().c_str();
38 QByteArray array(value->count(), 0);
39 value->copy(reinterpret_cast<Exiv2::byte *>(array.data()), Exiv2::invalidByteOrder);
40 return {QString(array.toBase64())};
41 }
42 case Exiv2::unsignedByte:
43 case Exiv2::unsignedShort:
44 case Exiv2::unsignedLong:
45 case Exiv2::signedShort:
46 case Exiv2::signedLong: {
47 if (value->count() == 1 && !forceSeq) {
48#if EXIV2_TEST_VERSION(0,28,0)
49 return {static_cast<int>(value->toUint32())};
50#else
51 return {static_cast<int>(value->toLong())};
52#endif
53 } else {
55 for (int i = 0; i < value->count(); i++)
56#if EXIV2_TEST_VERSION(0,28,0)
57 array.push_back({static_cast<int>(value->toUint32(i))});
58#else
59 array.push_back({static_cast<int>(value->toLong(i))});
60#endif
61 return {array, arrayType};
62 }
63 }
64 case Exiv2::asciiString:
65 case Exiv2::string:
66 case Exiv2::comment: // look at kexiv2 for the problem about decoding correctly that tag
67 return {QString::fromStdString(value->toString())};
68 case Exiv2::unsignedRational:
69 if (value->count() == 1 && !forceSeq) {
70 if (value->size() < 2) {
71 dbgMetaData << "Invalid size :" << value->size() << " value =" << value->toString().c_str();
72 return {};
73 }
74 return {KisMetaData::Rational(value->toRational().first, value->toRational().second)};
75 } else {
77#if EXIV2_TEST_VERSION(0,28,0)
78 for (size_t i = 0; i < value->count(); i++) {
79#else
80 for (long i = 0; i < value->count(); i++) {
81#endif
82 array.push_back(KisMetaData::Rational(value->toRational(i).first, value->toRational(i).second));
83 }
84 return {array, arrayType};
85 }
86 case Exiv2::signedRational:
87 if (value->count() == 1 && !forceSeq) {
88 if (value->size() < 2) {
89 dbgMetaData << "Invalid size :" << value->size() << " value =" << value->toString().c_str();
90 return {};
91 }
92 return {KisMetaData::Rational(value->toRational().first, value->toRational().second)};
93 } else {
95#if EXIV2_TEST_VERSION(0,28,0)
96 for (size_t i = 0; i < value->count(); i++) {
97#else
98 for (long i = 0; i < value->count(); i++) {
99#endif
100 array.push_back(KisMetaData::Rational(value->toRational(i).first, value->toRational(i).second));
101 }
102 return {array, arrayType};
103 }
104 case Exiv2::date:
105 case Exiv2::time:
106 return {QDateTime::fromString(QString::fromStdString(value->toString()), Qt::ISODate)};
107 case Exiv2::xmpText:
108 case Exiv2::xmpAlt:
109 case Exiv2::xmpBag:
110 case Exiv2::xmpSeq:
111 case Exiv2::langAlt:
112 default: {
113 dbgMetaData << "Unknown type id :" << value->typeId() << " value =" << value->toString().c_str();
114 // Q_ASSERT(false); // This point must never be reached !
115 return {};
116 }
117 }
118 dbgMetaData << "Unknown type id :" << value->typeId() << " value =" << value->toString().c_str();
119 // Q_ASSERT(false); // This point must never be reached !
120 return {};
121}
#define dbgMetaData
Definition kis_debug.h:61

References dbgMetaData, KisMetaData::Value::toString(), and value().

◆ kmdValueToExivValue()

Exiv2::Value * kmdValueToExivValue ( const KisMetaData::Value & value,
Exiv2::TypeId type )
inline

Convert a KisMetaData to an Exiv value.

Definition at line 179 of file kis_exiv2_common.h.

180{
181 switch (value.type()) {
183 return Exiv2::Value::create(Exiv2::invalidTypeId).release();
185 return variantToExivValue(value.asVariant(), type);
186 }
188 // Q_ASSERT(type == Exiv2::signedRational || type == Exiv2::unsignedRational);
189 if (type == Exiv2::signedRational) {
190 return new Exiv2::RationalValue({value.asRational().numerator, value.asRational().denominator});
191 } else {
192 return new Exiv2::URationalValue({value.asRational().numerator, value.asRational().denominator});
193 }
195 Q_FALLTHROUGH();
197 Q_FALLTHROUGH();
199 Q_FALLTHROUGH();
201 switch (type) {
202 case Exiv2::unsignedByte:
203 Q_FALLTHROUGH();
204 case Exiv2::unsignedShort:
205 return arrayToExivValue<uint16_t>(value);
206 case Exiv2::unsignedLong:
207 return arrayToExivValue<uint32_t>(value);
208 case Exiv2::signedShort:
209 return arrayToExivValue<int16_t>(value);
210 case Exiv2::signedLong:
211 return arrayToExivValue<int32_t>(value);
212 case Exiv2::asciiString:
213 Q_FALLTHROUGH();
214 case Exiv2::string: {
215 // Using toLatin1 here is not lossy for asciiString,
216 // but definitely is for string. IPTC allows UTF-8
217 // encoding which supersets ASCII. See:
218 // https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata#iim-properties
219 // https://doc.qt.io/qt-5/qstring.html#toLatin1
220 const QList<KisMetaData::Value> list = value.asArray();
221 QStringList result;
222 Q_FOREACH (const KisMetaData::Value &v, list) {
223 result << v.asVariant().value<QString>();
224 }
225 return new Exiv2::StringValue(result.join(',').toStdString());
226 }
227 case Exiv2::signedRational: {
228 Exiv2::RationalValue *exivValue = new Exiv2::RationalValue();
229 const QList<KisMetaData::Value> array = value.asArray();
230 exivValue->value_.reserve(static_cast<size_t>(array.size()));
231 Q_FOREACH (const KisMetaData::Value &item, array) {
233 exivValue->value_.emplace_back(value.numerator, value.denominator);
234 }
235 return exivValue;
236 }
237 case Exiv2::unsignedRational: {
238 Exiv2::URationalValue *exivValue = new Exiv2::URationalValue();
239 const QList<KisMetaData::Value> array = value.asArray();
240 exivValue->value_.reserve(static_cast<size_t>(array.size()));
241 Q_FOREACH (const KisMetaData::Value &item, array) {
243 exivValue->value_.emplace_back(static_cast<uint32_t>(value.numerator), static_cast<uint32_t>(value.denominator));
244 }
245 return exivValue;
246 }
247 default:
248 warnMetaData << type << " " << value.type() << value;
249 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(0 && "Unknown alternative array type", nullptr);
250 break;
251 }
252 break;
253 } break;
254 default:
255 warnMetaData << type << " " << value.type() << value;
256 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(false && "Unknown array type", nullptr);
257 break;
258 }
259 return nullptr;
260}
qreal v
KisMetaData::Rational asRational() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define warnMetaData
Definition kis_debug.h:103
Exiv2::Value * variantToExivValue(const QVariant &variant, Exiv2::TypeId type)

References KisMetaData::Value::AlternativeArray, KisMetaData::Value::asRational(), KisMetaData::Value::Invalid, KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, KisMetaData::Value::LangArray, KisMetaData::Value::OrderedArray, KisMetaData::Value::Rational, KisMetaData::Value::UnorderedArray, v, value(), KisMetaData::Value::Variant, variantToExivValue(), and warnMetaData.

◆ kmdValueToExivXmpValue()

Exiv2::Value * kmdValueToExivXmpValue ( const KisMetaData::Value & value)
inline

Convert a KisMetaData to an Exiv value, without knowing the targeted Exiv2::TypeId This function should be used for saving to XMP.

Definition at line 264 of file kis_exiv2_common.h.

265{
266 // Q_ASSERT(value.type() != KisMetaData::Value::Structure);
267 switch (value.type()) {
269 return new Exiv2::DataValue(Exiv2::invalidTypeId);
271 QVariant var = value.asVariant();
272 if (var.type() == QVariant::Bool) {
273 if (var.toBool()) {
274 return new Exiv2::XmpTextValue("True");
275 } else {
276 return new Exiv2::XmpTextValue("False");
277 }
278 } else {
279 // Q_ASSERT(var.canConvert(QVariant::String));
280 return new Exiv2::XmpTextValue(var.toString().toLatin1().constData());
281 }
282 }
284 QString rat = "%1 / %2";
285 rat = rat.arg(value.asRational().numerator);
286 rat = rat.arg(value.asRational().denominator);
287 return new Exiv2::XmpTextValue(rat.toLatin1().constData());
288 }
292 Exiv2::XmpArrayValue *arrV = new Exiv2::XmpArrayValue();
293 switch (value.type()) {
295 arrV->setXmpArrayType(Exiv2::XmpValue::xaSeq);
296 break;
298 arrV->setXmpArrayType(Exiv2::XmpValue::xaBag);
299 break;
301 arrV->setXmpArrayType(Exiv2::XmpValue::xaAlt);
302 break;
303 default:
304 // Cannot happen
305 ;
306 }
307 Q_FOREACH (const KisMetaData::Value &value, value.asArray()) {
308 QScopedPointer<Exiv2::Value> exivValue(kmdValueToExivXmpValue(value));
309 if (exivValue) {
310 arrV->read(exivValue->toString());
311 }
312 }
313 return arrV;
314 }
316 Exiv2::Value *arrV = new Exiv2::LangAltValue;
317 QMap<QString, KisMetaData::Value> langArray = value.asLangArray();
318 for (auto it = langArray.begin(); it != langArray.end(); ++it) {
319 QString exivVal;
320 if (it.key() != "x-default") {
321 exivVal = "lang=" + it.key() + ' ';
322 }
323 // Q_ASSERT(it.value().type() == KisMetaData::Value::Variant);
324 QVariant var = it.value().asVariant();
325 // Q_ASSERT(var.type() == QVariant::String);
326 exivVal += var.toString();
327 arrV->read(exivVal.toLatin1().constData());
328 }
329 return arrV;
330 }
332 default: {
333 warnKrita << "KisExiv2: Unhandled value type";
334 return nullptr;
335 }
336 }
337 warnKrita << "KisExiv2: Unhandled value type";
338 return nullptr;
339}
QList< KisMetaData::Value > asArray() const
#define warnKrita
Definition kis_debug.h:87
Exiv2::Value * kmdValueToExivXmpValue(const KisMetaData::Value &value)

References KisMetaData::Value::AlternativeArray, KisMetaData::Value::asArray(), KisMetaData::Value::Invalid, kmdValueToExivXmpValue(), KisMetaData::Value::LangArray, KisMetaData::Value::OrderedArray, KisMetaData::Value::Rational, KisMetaData::Value::Structure, KisMetaData::Value::UnorderedArray, value(), KisMetaData::Value::Variant, and warnKrita.

◆ variantToExivValue()

Exiv2::Value * variantToExivValue ( const QVariant & variant,
Exiv2::TypeId type )
inline

Definition at line 124 of file kis_exiv2_common.h.

125{
126 switch (type) {
127 case Exiv2::undefined: {
128 const QByteArray arr = QByteArray::fromBase64(variant.toString().toLatin1());
129 return new Exiv2::DataValue(reinterpret_cast<const Exiv2::byte *>(arr.data()), arr.size());
130 }
131 case Exiv2::unsignedByte:
132 return new Exiv2::ValueType<uint16_t>((uint16_t)variant.toUInt());
133 case Exiv2::unsignedShort:
134 return new Exiv2::ValueType<uint16_t>((uint16_t)variant.toUInt());
135 case Exiv2::unsignedLong:
136 return new Exiv2::ValueType<uint32_t>((uint32_t)variant.toUInt());
137 case Exiv2::signedShort:
138 return new Exiv2::ValueType<int16_t>((int16_t)variant.toInt());
139 case Exiv2::signedLong:
140 return new Exiv2::ValueType<int32_t>((int32_t)variant.toInt());
141 case Exiv2::date: {
142 QDate date = variant.toDate();
143 return new Exiv2::DateValue(date.year(), date.month(), date.day());
144 }
145 case Exiv2::asciiString:
146 if (variant.type() == QVariant::DateTime) {
147 return new Exiv2::AsciiValue(
148 qPrintable(QLocale::c().toString(variant.toDateTime(), QStringLiteral("yyyy:MM:dd hh:mm:ss"))));
149 } else
150 return new Exiv2::AsciiValue(qPrintable(variant.toString()));
151 case Exiv2::string: {
152 if (variant.type() == QVariant::DateTime) {
153 return new Exiv2::StringValue(
154 qPrintable(QLocale::c().toString(variant.toDateTime(), QStringLiteral("yyyy:MM:dd hh:mm:ss"))));
155 } else
156 return new Exiv2::StringValue(qPrintable(variant.toString()));
157 }
158 case Exiv2::comment:
159 return new Exiv2::CommentValue(qPrintable(variant.toString()));
160 default:
161 dbgMetaData << "Unhandled type:" << type;
162 // Q_ASSERT(false);
163 return nullptr;
164 }
165}
QString toString(const QString &value)

References dbgMetaData.