Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_exif_io.cpp File Reference
#include "kis_exif_io.h"
#include <exiv2/error.hpp>
#include <exiv2/exif.hpp>
#include <QByteArray>
#include <QDate>
#include <QDateTime>
#include <QIODevice>
#include <QTextCodec>
#include <QTime>
#include <QVariant>
#include <QtEndian>
#include <kis_debug.h>
#include <kis_exiv2_common.h>
#include <kis_meta_data_entry.h>
#include <kis_meta_data_schema.h>
#include <kis_meta_data_schema_registry.h>
#include <kis_meta_data_store.h>
#include <kis_meta_data_tags.h>
#include <kis_meta_data_value.h>

Go to the source code of this file.

Functions

KisMetaData::Value cfaPatternExifToKMD (const Exiv2::Value::AutoPtr value, Exiv2::ByteOrder order)
 
Exiv2::Value * cfaPatternKMDToExif (const KisMetaData::Value &value)
 
KisMetaData::Value deviceSettingDescriptionExifToKMD (const Exiv2::Value::AutoPtr value)
 
Exiv2::Value * deviceSettingDescriptionKMDToExif (const KisMetaData::Value &value)
 
KisMetaData::Value exifArrayToKMDIntOrderedArray (const Exiv2::Value::AutoPtr value)
 
KisMetaData::Value exifOECFToKMDOECFStructure (const Exiv2::Value::AutoPtr value, Exiv2::ByteOrder order)
 
KisMetaData::Value exifVersionToKMDValue (const Exiv2::Value::AutoPtr value)
 
QDateTime exivValueToDateTime (const Exiv2::Value::AutoPtr value)
 
template<typename T >
fixEndianness (T v, Exiv2::ByteOrder order)
 
KisMetaData::Value flashExifToKMD (const Exiv2::Value::AutoPtr value)
 
Exiv2::Value * flashKMDToExif (const KisMetaData::Value &value)
 
Exiv2::ByteOrder invertByteOrder (Exiv2::ByteOrder order)
 
Exiv2::Value * kmdIntOrderedArrayToExifArray (const KisMetaData::Value &value)
 
Exiv2::Value * kmdOECFStructureToExifOECF (const KisMetaData::Value &value)
 
Exiv2::Value * kmdValueToExifVersion (const KisMetaData::Value &value)
 

Function Documentation

◆ cfaPatternExifToKMD()

KisMetaData::Value cfaPatternExifToKMD ( const Exiv2::Value::AutoPtr value,
Exiv2::ByteOrder order )

Definition at line 311 of file kis_exif_io.cpp.

313{
314 QMap<QString, KisMetaData::Value> cfaPatternStructure;
315 const Exiv2::DataValue *dvalue = dynamic_cast<const Exiv2::DataValue *>(&*value);
316 Q_ASSERT(dvalue);
317 QByteArray array(dvalue->count(), 0);
318 dvalue->copy((Exiv2::byte *)array.data());
319#if EXIV2_TEST_VERSION(0,28,0)
320 size_t columns = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[0], order);
321 size_t rows = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[1], order);
322#else
323 int columns = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[0], order);
324 int rows = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[1], order);
325#endif
326 if ((columns * rows + 4)
327 != dvalue->count()) { // Sometime byteOrder get messed up (especially if metadata got saved with kexiv2 library,
328 // or any library that doesn't save back with the same byte order as the camera)
329 order = invertByteOrder(order);
330 columns = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[0], order);
331 rows = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[1], order);
332 }
333 QVariant qcolumns, qrows;
334 qcolumns.setValue(columns);
335 qrows.setValue(rows);
336 cfaPatternStructure["Columns"] = KisMetaData::Value(qcolumns);
337 cfaPatternStructure["Rows"] = KisMetaData::Value(qrows);
339 int index = 4;
340 for (int i = 0; i < columns * rows; i++) {
341 values.append(KisMetaData::Value(*(array.data() + index)));
342 index++;
343 }
344 cfaPatternStructure["Values"] = KisMetaData::Value(values, KisMetaData::Value::OrderedArray);
345 dbgMetaData << "CFAPattern " << ppVar(columns) << " " << ppVar(rows) << ppVar(values.size())
346 << ppVar(dvalue->count());
347 return KisMetaData::Value(cfaPatternStructure);
348}
float value(const T *src, size_t ch)
#define ppVar(var)
Definition kis_debug.h:155
#define dbgMetaData
Definition kis_debug.h:61
Exiv2::ByteOrder invertByteOrder(Exiv2::ByteOrder order)

References dbgMetaData, invertByteOrder(), KisMetaData::Value::OrderedArray, ppVar, and value().

◆ cfaPatternKMDToExif()

Exiv2::Value * cfaPatternKMDToExif ( const KisMetaData::Value & value)

Definition at line 350 of file kis_exif_io.cpp.

351{
352 QMap<QString, KisMetaData::Value> cfaStructure = value.asStructure();
353 const quint16 columns = static_cast<quint16>(cfaStructure["Columns"].asVariant().toUInt());
354 const quint16 rows = static_cast<quint16>(cfaStructure["Rows"].asVariant().toUInt());
355
356 QList<KisMetaData::Value> values = cfaStructure["Values"].asArray();
357 Q_ASSERT(columns * rows == values.size());
358 QByteArray array(4 + columns * rows, 0);
359 (reinterpret_cast<quint16 *>(array.data()))[0] = columns;
360 (reinterpret_cast<quint16 *>(array.data()))[1] = rows;
361 for (int i = 0; i < columns * rows; i++) {
362 const quint8 val = (quint8)values[i].asVariant().toUInt();
363 *(array.data() + 4 + i) = (char)val;
364 }
365 dbgMetaData << "Cfa Array " << ppVar(columns) << ppVar(rows) << ppVar(array.size());
366 return new Exiv2::DataValue((const Exiv2::byte *)array.data(), array.size());
367}

References dbgMetaData, ppVar, and value().

◆ deviceSettingDescriptionExifToKMD()

KisMetaData::Value deviceSettingDescriptionExifToKMD ( const Exiv2::Value::AutoPtr value)

Definition at line 251 of file kis_exif_io.cpp.

253{
254 QMap<QString, KisMetaData::Value> deviceSettingStructure;
255 QByteArray array;
256
257 const Exiv2::DataValue *dvalue = dynamic_cast<const Exiv2::DataValue *>(&*value);
258 if (dvalue) {
259 array.resize(dvalue->count());
260 dvalue->copy((Exiv2::byte *)array.data());
261 } else {
262 Q_ASSERT(value->typeId() == Exiv2::unsignedShort);
263 array.resize(2 * value->count());
264 value->copy((Exiv2::byte *)array.data(), Exiv2::littleEndian);
265 }
266 int columns = (reinterpret_cast<quint16 *>(array.data()))[0];
267 int rows = (reinterpret_cast<quint16 *>(array.data()))[1];
268 deviceSettingStructure["Columns"] = KisMetaData::Value(columns);
269 deviceSettingStructure["Rows"] = KisMetaData::Value(rows);
271 QByteArray null(2, 0);
272
273 for (int index = 4; index < array.size();) {
274 const int lastIndex = array.indexOf(null, index);
275 if (lastIndex < 0)
276 break; // Data is not a String, ignore
277 const int numChars = (lastIndex - index) / 2; // including trailing zero
278
279 QString setting = QString::fromUtf16((ushort *)(void *)(array.data() + index), numChars);
280 index = lastIndex + 2;
281 dbgMetaData << "Setting << " << setting;
282 settings.append(KisMetaData::Value(setting));
283 }
284 deviceSettingStructure["Settings"] = KisMetaData::Value(settings, KisMetaData::Value::OrderedArray);
285 return KisMetaData::Value(deviceSettingStructure);
286}

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

◆ deviceSettingDescriptionKMDToExif()

Exiv2::Value * deviceSettingDescriptionKMDToExif ( const KisMetaData::Value & value)

Definition at line 288 of file kis_exif_io.cpp.

289{
290 QMap<QString, KisMetaData::Value> deviceSettingStructure = value.asStructure();
291 const quint16 columns = static_cast<quint16>(deviceSettingStructure["Columns"].asVariant().toUInt());
292 quint16 rows = static_cast<quint16>(deviceSettingStructure["Rows"].asVariant().toUInt());
293
294 QTextCodec *codec = QTextCodec::codecForName("UTF-16");
295
296 QList<KisMetaData::Value> settings = deviceSettingStructure["Settings"].asArray();
297 QByteArray array(4, 0);
298 (reinterpret_cast<quint16 *>(array.data()))[0] = columns;
299 (reinterpret_cast<quint16 *>(array.data()))[1] = rows;
300 for (const KisMetaData::Value &v : settings) {
301 const QString str = v.asVariant().toString();
302 QByteArray setting = codec->fromUnicode(str);
303 array.append(setting);
304 }
305 return new Exiv2::DataValue((const Exiv2::byte *)array.data(), array.size());
306}
qreal v

References v, and value().

◆ exifArrayToKMDIntOrderedArray()

KisMetaData::Value exifArrayToKMDIntOrderedArray ( const Exiv2::Value::AutoPtr value)

Definition at line 65 of file kis_exif_io.cpp.

67{
69 const Exiv2::DataValue *dvalue = dynamic_cast<const Exiv2::DataValue *>(&*value);
70 if (dvalue) {
71#if EXIV2_TEST_VERSION(0,28,0)
72 for (size_t i = 0; i < dvalue->count(); i++) {
73 v.push_back({(int)dvalue->toUint32(i)});
74#else
75 for (long i = 0; i < dvalue->count(); i++) {
76 v.push_back({(int)dvalue->toLong(i)});
77#endif
78 }
79 } else {
80 Q_ASSERT(value->typeId() == Exiv2::asciiString);
81 QString str = QString::fromLatin1(value->toString().c_str());
82 v.push_back(KisMetaData::Value(str.toInt()));
83 }
85}

References KisMetaData::Value::OrderedArray, v, and value().

◆ exifOECFToKMDOECFStructure()

KisMetaData::Value exifOECFToKMDOECFStructure ( const Exiv2::Value::AutoPtr value,
Exiv2::ByteOrder order )

Definition at line 138 of file kis_exif_io.cpp.

140{
141 QMap<QString, KisMetaData::Value> oecfStructure;
142 const Exiv2::DataValue *dvalue = dynamic_cast<const Exiv2::DataValue *>(&*value);
143 Q_ASSERT(dvalue);
144 QByteArray array(dvalue->count(), 0);
145
146 dvalue->copy((Exiv2::byte *)array.data());
147#if EXIV2_TEST_VERSION(0,28,0)
148 size_t columns = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[0], order);
149 size_t rows = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[1], order);
150#else
151 int columns = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[0], order);
152 int rows = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[1], order);
153#endif
154
155 if ((columns * rows + 4)
156 > dvalue->count()) { // Sometime byteOrder get messed up (especially if metadata got saved with kexiv2 library,
157 // or any library that doesn't save back with the same byte order as the camera)
158 order = invertByteOrder(order);
159#if EXIV2_TEST_VERSION(0,28,0)
160 columns = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[0], order);
161 rows = fixEndianness<qsizetype>((reinterpret_cast<qsizetype *>(array.data()))[1], order);
162#else
163 columns = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[0], order);
164 rows = fixEndianness<quint16>((reinterpret_cast<quint16 *>(array.data()))[1], order);
165#endif
166 Q_ASSERT((columns * rows + 4) > dvalue->count());
167 }
168 QVariant qcolumns, qrows;
169 qcolumns.setValue(columns);
170 qrows.setValue(rows);
171 oecfStructure["Columns"] = KisMetaData::Value(qcolumns);
172 oecfStructure["Rows"] = KisMetaData::Value(qrows);
173 int index = 4;
175#if EXIV2_TEST_VERSION(0,28,0)
176 for (size_t i = 0; i < columns; i++) {
177#else
178 for (int i = 0; i < columns; i++) {
179#endif
180 int lastIndex = array.indexOf((char)0, index);
181 QString name = array.mid(index, lastIndex - index);
182 if (index != lastIndex) {
183 index = lastIndex + 1;
184 dbgMetaData << "Name [" << i << "] =" << name;
185 names.append(KisMetaData::Value(name));
186 } else {
187 names.append(KisMetaData::Value(""));
188 }
189 }
190
191 oecfStructure["Names"] = KisMetaData::Value(names, KisMetaData::Value::OrderedArray);
193 qint32 *dataIt = reinterpret_cast<qint32 *>(array.data() + index);
194#if EXIV2_TEST_VERSION(0,28,0)
195 for (size_t i = 0; i < columns; i++) {
196 for (size_t j = 0; j < rows; j++) {
197#else
198 for (int i = 0; i < columns; i++) {
199 for (int j = 0; j < rows; j++) {
200#endif
201 values.append(KisMetaData::Value(
202 KisMetaData::Rational(fixEndianness<qint32>(dataIt[0], order), fixEndianness<qint32>(dataIt[1], order))));
203 dataIt += 2;
204 }
205 }
206 oecfStructure["Values"] = KisMetaData::Value(values, KisMetaData::Value::OrderedArray);
207 dbgMetaData << "OECF: " << ppVar(columns) << ppVar(rows) << ppVar(dvalue->count());
208 return KisMetaData::Value(oecfStructure);
209}
const char * name(StandardAction id)

References dbgMetaData, invertByteOrder(), KisMetaData::Value::OrderedArray, ppVar, and value().

◆ exifVersionToKMDValue()

KisMetaData::Value exifVersionToKMDValue ( const Exiv2::Value::AutoPtr value)

Definition at line 37 of file kis_exif_io.cpp.

39{
40 const Exiv2::DataValue *dvalue = dynamic_cast<const Exiv2::DataValue *>(&*value);
41 if (dvalue) {
42 Q_ASSERT(dvalue);
43 QByteArray array(dvalue->count(), 0);
44 dvalue->copy((Exiv2::byte *)array.data());
45 return KisMetaData::Value(QString(array));
46 } else {
47 Q_ASSERT(value->typeId() == Exiv2::asciiString);
48 return KisMetaData::Value(QString::fromLatin1(value->toString().c_str()));
49 }
50}

References value().

◆ exivValueToDateTime()

QDateTime exivValueToDateTime ( const Exiv2::Value::AutoPtr value)

Definition at line 100 of file kis_exif_io.cpp.

102{
103 return QDateTime::fromString(value->toString().c_str(), Qt::ISODate);
104}

References value().

◆ fixEndianness()

template<typename T >
T fixEndianness ( T v,
Exiv2::ByteOrder order )
inline

Definition at line 107 of file kis_exif_io.cpp.

108{
109 switch (order) {
110 case Exiv2::invalidByteOrder:
111 return v;
112 case Exiv2::littleEndian:
113 return qFromLittleEndian<T>(v);
114 case Exiv2::bigEndian:
115 return qFromBigEndian<T>(v);
116 }
117 warnKrita << "KisExifIO: unknown byte order";
118 return v;
119}
#define warnKrita
Definition kis_debug.h:87

References v, and warnKrita.

◆ flashExifToKMD()

KisMetaData::Value flashExifToKMD ( const Exiv2::Value::AutoPtr value)

Definition at line 374 of file kis_exif_io.cpp.

376{
377#if EXIV2_TEST_VERSION(0,28,0)
378 const uint16_t v = static_cast<uint16_t>(value->toUint32());
379#else
380 const uint16_t v = static_cast<uint16_t>(value->toLong());
381#endif
382 QMap<QString, KisMetaData::Value> flashStructure;
383 bool fired = (v & 0x01); // bit 1 is whether flash was fired or not
384 flashStructure["Fired"] = QVariant(fired);
385 int ret = ((v >> 1) & 0x03); // bit 2 and 3 are Return
386 flashStructure["Return"] = QVariant(ret);
387 int mode = ((v >> 3) & 0x03); // bit 4 and 5 are Mode
388 flashStructure["Mode"] = QVariant(mode);
389 bool function = ((v >> 5) & 0x01); // bit 6 if function
390 flashStructure["Function"] = QVariant(function);
391 bool redEye = ((v >> 6) & 0x01); // bit 7 if function
392 flashStructure["RedEyeMode"] = QVariant(redEye);
393 return KisMetaData::Value(flashStructure);
394}

References v, and value().

◆ flashKMDToExif()

Exiv2::Value * flashKMDToExif ( const KisMetaData::Value & value)

Definition at line 396 of file kis_exif_io.cpp.

397{
398 uint16_t v = 0;
399 QMap<QString, KisMetaData::Value> flashStructure = value.asStructure();
400 v = flashStructure["Fired"].asVariant().toBool();
401 v |= ((flashStructure["Return"].asVariant().toInt() & 0x03) << 1);
402 v |= ((flashStructure["Mode"].asVariant().toInt() & 0x03) << 3);
403 v |= ((flashStructure["Function"].asVariant().toInt() & 0x03) << 5);
404 v |= ((flashStructure["RedEyeMode"].asVariant().toInt() & 0x03) << 6);
405 return new Exiv2::ValueType<uint16_t>(v);
406}

References v, and value().

◆ invertByteOrder()

Exiv2::ByteOrder invertByteOrder ( Exiv2::ByteOrder order)

Definition at line 121 of file kis_exif_io.cpp.

122{
123 switch (order) {
124 case Exiv2::littleEndian:
125 return Exiv2::bigEndian;
126 case Exiv2::bigEndian:
127 return Exiv2::littleEndian;
128 case Exiv2::invalidByteOrder:
129 warnKrita << "KisExifIO: Can't invert Exiv2::invalidByteOrder";
130 return Exiv2::invalidByteOrder;
131 }
132 return Exiv2::invalidByteOrder;
133}

References warnKrita.

◆ kmdIntOrderedArrayToExifArray()

Exiv2::Value * kmdIntOrderedArrayToExifArray ( const KisMetaData::Value & value)

Definition at line 88 of file kis_exif_io.cpp.

89{
90 std::vector<Exiv2::byte> v;
91 for (const KisMetaData::Value &it : value.asArray()) {
92 v.push_back(static_cast<uint8_t>(it.asVariant().toInt(0)));
93 }
94 return new Exiv2::DataValue(v.data(), static_cast<long>(v.size()));
95}

References v, and value().

◆ kmdOECFStructureToExifOECF()

Exiv2::Value * kmdOECFStructureToExifOECF ( const KisMetaData::Value & value)

Definition at line 211 of file kis_exif_io.cpp.

212{
213 QMap<QString, KisMetaData::Value> oecfStructure = value.asStructure();
214 const quint16 columns = static_cast<quint16>(oecfStructure["Columns"].asVariant().toUInt());
215 const quint16 rows = static_cast<quint16>(oecfStructure["Rows"].asVariant().toUInt());
216
217 QList<KisMetaData::Value> names = oecfStructure["Names"].asArray();
218 QList<KisMetaData::Value> values = oecfStructure["Values"].asArray();
219 Q_ASSERT(columns * rows == values.size());
220 int length = 4 + rows * columns * 8; // The 4 byte for storing rows/columns and the rows*columns*sizeof(rational)
221 bool saveNames = (!names.empty() && names[0].asVariant().toString().size() > 0);
222 if (saveNames) {
223 for (int i = 0; i < columns; i++) {
224 length += names[i].asVariant().toString().size() + 1;
225 }
226 }
227 QByteArray array(length, 0);
228 (reinterpret_cast<quint16 *>(array.data()))[0] = columns;
229 (reinterpret_cast<quint16 *>(array.data()))[1] = rows;
230 int index = 4;
231 if (saveNames) {
232 for (int i = 0; i < columns; i++) {
233 QByteArray name = names[i].asVariant().toString().toLatin1();
234 name.append((char)0);
235 memcpy(array.data() + index, name.data(), static_cast<size_t>(name.size()));
236 index += name.size();
237 }
238 }
239 qint32 *dataIt = reinterpret_cast<qint32 *>(array.data() + index);
240 for (const KisMetaData::Value &it : values) {
241 dataIt[0] = it.asRational().numerator;
242 dataIt[1] = it.asRational().denominator;
243 dataIt += 2;
244 }
245 return new Exiv2::DataValue((const Exiv2::byte *)array.data(), array.size());
246}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82

References length(), and value().

◆ kmdValueToExifVersion()

Exiv2::Value * kmdValueToExifVersion ( const KisMetaData::Value & value)

Definition at line 53 of file kis_exif_io.cpp.

54{
55 Exiv2::DataValue *dvalue = new Exiv2::DataValue;
56 QString ver = value.asVariant().toString();
57 dvalue->read((const Exiv2::byte *)ver.toLatin1().constData(), ver.size());
58 return dvalue;
59}

References value().