1 /*
2 This file is part of darktable,
3 Copyright (C) 2009-2021 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #define __STDC_FORMAT_MACROS
20
21 extern "C" {
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <errno.h>
27 #include <glib.h>
28 #include <sqlite3.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <zlib.h>
34
35 #include "control/control.h"
36 }
37
38 #include <cassert>
39 #include <cmath>
40 #include <fstream>
41 #include <iostream>
42 #include <sstream>
43 #include <string>
44
45 #include <exiv2/exiv2.hpp>
46
47 #if defined(_WIN32) && defined(EXV_UNICODE_PATH)
48 #define WIDEN(s) pugi::as_wide(s)
49 #else
50 #define WIDEN(s) (s)
51 #endif
52
53 #include <pugixml.hpp>
54
55 using namespace std;
56
57 extern "C" {
58 #include "common/colorlabels.h"
59 #include "common/darktable.h"
60 #include "common/debug.h"
61 #include "common/image_cache.h"
62 #include "common/imageio.h"
63 #include "common/exif.h"
64 #include "common/imageio_jpeg.h"
65 #include "common/metadata.h"
66 #include "common/ratings.h"
67 #include "common/tags.h"
68 #include "common/iop_order.h"
69 #include "common/variables.h"
70 #include "common/utility.h"
71 #include "common/history.h"
72 #include "control/conf.h"
73 #include "develop/imageop.h"
74 #include "develop/blend.h"
75 #include "develop/masks.h"
76 }
77
78 #include "external/adobe_coeff.c"
79
80 #define DT_XMP_EXIF_VERSION 4
81
82 // persistent list of exiv2 tags. set up in dt_init()
83 static GList *exiv2_taglist = NULL;
84
_get_exiv2_type(const int type)85 static const char *_get_exiv2_type(const int type)
86 {
87 switch(type)
88 {
89 case 1:
90 return "Byte";
91 case 2:
92 return "Ascii";
93 case 3:
94 return "Short";
95 case 4:
96 return "Long";
97 case 5:
98 return "Rational"; // two LONGs: numerator and denumerator of a fraction
99 case 6:
100 return "SByte";
101 case 7:
102 return "Undefined";
103 case 8:
104 return "SShort";
105 case 9:
106 return "SLong";
107 case 10:
108 return "SRational"; // two SLONGs: numerator and denumerator of a fraction.
109 case 11:
110 return "Float"; // single precision (4-byte) IEEE format
111 case 12:
112 return "Double"; // double precision (8-byte) IEEE format.
113 case 13:
114 return "Ifd"; // 32-bit (4-byte) unsigned integer
115 case 16:
116 return "LLong"; // 64-bit (8-byte) unsigned integer
117 case 17:
118 return "LLong"; // 64-bit (8-byte) signed integer
119 case 18:
120 return "Ifd8"; // 64-bit (8-byte) unsigned integer
121 case 0x10000:
122 return "String";
123 case 0x10001:
124 return "Date";
125 case 0x10002:
126 return "Time";
127 case 0x10003:
128 return "Comment";
129 case 0x10004:
130 return "Directory";
131 case 0x10005:
132 return "XmpText";
133 case 0x10006:
134 return "XmpAlt";
135 case 0x10007:
136 return "XmpBag";
137 case 0x10008:
138 return "XmpSeq";
139 case 0x10009:
140 return "LangAlt";
141 case 0x1fffe:
142 return "Invalid";
143 case 0x1ffff:
144 return "LastType";
145 default:
146 return "Invalid";
147 }
148 }
149
_get_xmp_tags(const char * prefix,GList ** taglist)150 static void _get_xmp_tags(const char *prefix, GList **taglist)
151 {
152 const Exiv2::XmpPropertyInfo *pl = Exiv2::XmpProperties::propertyList(prefix);
153 if(pl)
154 {
155 for (int i = 0; pl[i].name_ != 0; ++i)
156 {
157 char *tag = dt_util_dstrcat(NULL, "Xmp.%s.%s,%s", prefix, pl[i].name_, _get_exiv2_type(pl[i].typeId_));
158 *taglist = g_list_prepend(*taglist, tag);
159 }
160 }
161 }
162
dt_exif_set_exiv2_taglist()163 void dt_exif_set_exiv2_taglist()
164 {
165 if(exiv2_taglist) return;
166
167 try
168 {
169 const Exiv2::GroupInfo *groupList = Exiv2::ExifTags::groupList();
170 if(groupList)
171 {
172 while(groupList->tagList_)
173 {
174 const std::string groupName(groupList->groupName_);
175 if(groupName.substr(0, 3) != "Sub" &&
176 groupName != "Image2" &&
177 groupName != "Image3" &&
178 groupName != "Thumbnail"
179 )
180 {
181 const Exiv2::TagInfo *tagInfo = groupList->tagList_();
182 while(tagInfo->tag_ != 0xFFFF)
183 {
184 char *tag = dt_util_dstrcat(NULL, "Exif.%s.%s,%s", groupList->groupName_, tagInfo->name_, _get_exiv2_type(tagInfo->typeId_));
185 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
186 tagInfo++;
187 }
188 }
189 groupList++;
190 }
191 }
192
193 const Exiv2::DataSet *iptcEnvelopeList = Exiv2::IptcDataSets::envelopeRecordList();
194 while(iptcEnvelopeList->number_ != 0xFFFF)
195 {
196 char *tag = dt_util_dstrcat(NULL, "Iptc.Envelope.%s,%s%s", iptcEnvelopeList->name_,
197 _get_exiv2_type(iptcEnvelopeList->type_),
198 iptcEnvelopeList->repeatable_ ? "-R" : "");
199 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
200 iptcEnvelopeList++;
201 }
202
203 const Exiv2::DataSet *iptcApplication2List = Exiv2::IptcDataSets::application2RecordList();
204 while(iptcApplication2List->number_ != 0xFFFF)
205 {
206 char *tag = dt_util_dstrcat(NULL, "Iptc.Application2.%s,%s%s", iptcApplication2List->name_,
207 _get_exiv2_type(iptcApplication2List->type_),
208 iptcApplication2List->repeatable_ ? "-R" : "");
209 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
210 iptcApplication2List++;
211 }
212
213 _get_xmp_tags("dc", &exiv2_taglist);
214 _get_xmp_tags("xmp", &exiv2_taglist);
215 _get_xmp_tags("xmpRights", &exiv2_taglist);
216 _get_xmp_tags("xmpMM", &exiv2_taglist);
217 _get_xmp_tags("xmpBJ", &exiv2_taglist);
218 _get_xmp_tags("xmpTPg", &exiv2_taglist);
219 _get_xmp_tags("xmpDM", &exiv2_taglist);
220 _get_xmp_tags("pdf", &exiv2_taglist);
221 _get_xmp_tags("photoshop", &exiv2_taglist);
222 _get_xmp_tags("crs", &exiv2_taglist);
223 _get_xmp_tags("tiff", &exiv2_taglist);
224 _get_xmp_tags("exif", &exiv2_taglist);
225 _get_xmp_tags("exifEX", &exiv2_taglist);
226 _get_xmp_tags("aux", &exiv2_taglist);
227 _get_xmp_tags("iptc", &exiv2_taglist);
228 _get_xmp_tags("iptcExt", &exiv2_taglist);
229 _get_xmp_tags("plus", &exiv2_taglist);
230 _get_xmp_tags("mwg-rs", &exiv2_taglist);
231 _get_xmp_tags("mwg-kw", &exiv2_taglist);
232 _get_xmp_tags("dwc", &exiv2_taglist);
233 _get_xmp_tags("dcterms", &exiv2_taglist);
234 _get_xmp_tags("digiKam", &exiv2_taglist);
235 _get_xmp_tags("kipi", &exiv2_taglist);
236 _get_xmp_tags("GPano", &exiv2_taglist);
237 _get_xmp_tags("lr", &exiv2_taglist);
238 _get_xmp_tags("MP", &exiv2_taglist);
239 _get_xmp_tags("MPRI", &exiv2_taglist);
240 _get_xmp_tags("MPReg", &exiv2_taglist);
241 _get_xmp_tags("acdsee", &exiv2_taglist);
242 _get_xmp_tags("mediapro", &exiv2_taglist);
243 _get_xmp_tags("expressionmedia", &exiv2_taglist);
244 _get_xmp_tags("MicrosoftPhoto", &exiv2_taglist);
245 }
246 catch (Exiv2::AnyError& e)
247 {
248 std::string s(e.what());
249 std::cerr << "[exiv2 taglist] " << s << std::endl;
250 }
251 }
252
dt_exif_get_exiv2_taglist()253 const GList* dt_exif_get_exiv2_taglist()
254 {
255 if(!exiv2_taglist)
256 dt_exif_set_exiv2_taglist();
257 return exiv2_taglist;
258 }
259
_exif_get_exiv2_tag_type(const char * tagname)260 static const char *_exif_get_exiv2_tag_type(const char *tagname)
261 {
262 if(!tagname) return NULL;
263 for(GList *tag = exiv2_taglist; tag; tag = g_list_next(tag))
264 {
265 char *t = (char *)tag->data;
266 if(g_str_has_prefix(t, tagname) && t[strlen(tagname)] == ',')
267 if(t)
268 {
269 t += strlen(tagname) + 1;
270 return t;
271 }
272 }
273 return NULL;
274 }
275
276 // exiv2's readMetadata is not thread safe in 0.26. so we lock it. since readMetadata might throw an exception we
277 // wrap it into some c++ magic to make sure we unlock in all cases. well, actually not magic but basic raii.
278 // FIXME: check again once we rely on 0.27
279 class Lock
280 {
281 public:
Lock()282 Lock() { dt_pthread_mutex_lock(&darktable.exiv2_threadsafe); }
~Lock()283 ~Lock() { dt_pthread_mutex_unlock(&darktable.exiv2_threadsafe); }
284 };
285
286 #define read_metadata_threadsafe(image) \
287 { \
288 Lock lock; \
289 image->readMetadata(); \
290 }
291
292 static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos);
293 static void read_xmp_timestamps(Exiv2::XmpData &xmpData, dt_image_t *img);
294
295 // this array should contain all XmpBag and XmpSeq keys used by dt
296 const char *dt_xmp_keys[]
297 = { "Xmp.dc.subject", "Xmp.lr.hierarchicalSubject", "Xmp.darktable.colorlabels", "Xmp.darktable.history",
298 "Xmp.darktable.history_modversion", "Xmp.darktable.history_enabled", "Xmp.darktable.history_end",
299 "Xmp.darktable.iop_order_version", "Xmp.darktable.iop_order_list",
300 "Xmp.darktable.history_operation", "Xmp.darktable.history_params", "Xmp.darktable.blendop_params",
301 "Xmp.darktable.blendop_version", "Xmp.darktable.multi_priority", "Xmp.darktable.multi_name",
302 "Xmp.darktable.iop_order",
303 "Xmp.darktable.xmp_version", "Xmp.darktable.raw_params", "Xmp.darktable.auto_presets_applied",
304 "Xmp.darktable.mask_id", "Xmp.darktable.mask_type", "Xmp.darktable.mask_name",
305 "Xmp.darktable.masks_history", "Xmp.darktable.mask_num", "Xmp.darktable.mask_points",
306 "Xmp.darktable.mask_version", "Xmp.darktable.mask", "Xmp.darktable.mask_nb", "Xmp.darktable.mask_src",
307 "Xmp.darktable.history_basic_hash", "Xmp.darktable.history_auto_hash", "Xmp.darktable.history_current_hash",
308 "Xmp.darktable.import_timestamp", "Xmp.darktable.change_timestamp",
309 "Xmp.darktable.export_timestamp", "Xmp.darktable.print_timestamp",
310 "Xmp.acdsee.notes", "Xmp.darktable.version_name",
311 "Xmp.dc.creator", "Xmp.dc.publisher", "Xmp.dc.title", "Xmp.dc.description", "Xmp.dc.rights",
312 "Xmp.xmpMM.DerivedFrom" };
313
314 static const guint dt_xmp_keys_n = G_N_ELEMENTS(dt_xmp_keys); // the number of XmpBag XmpSeq keys that dt uses
315
316 // inspired by ufraw_exiv2.cc:
317
dt_strlcpy_to_utf8(char * dest,size_t dest_max,Exiv2::ExifData::const_iterator & pos,Exiv2::ExifData & exifData)318 static void dt_strlcpy_to_utf8(char *dest, size_t dest_max, Exiv2::ExifData::const_iterator &pos,
319 Exiv2::ExifData &exifData)
320 {
321 std::string str = pos->print(&exifData);
322
323 char *s = g_locale_to_utf8(str.c_str(), str.length(), NULL, NULL, NULL);
324 if(s != NULL)
325 {
326 g_strlcpy(dest, s, dest_max);
327 g_free(s);
328 }
329 else
330 {
331 g_strlcpy(dest, str.c_str(), dest_max);
332 }
333 }
334
335 // function to remove known dt keys and subtrees from xmpdata, so not to append them twice
336 // this should work because dt first reads all known keys
dt_remove_known_keys(Exiv2::XmpData & xmp)337 static void dt_remove_known_keys(Exiv2::XmpData &xmp)
338 {
339 xmp.sortByKey();
340 for(unsigned int i = 0; i < dt_xmp_keys_n; i++)
341 {
342 Exiv2::XmpData::iterator pos = xmp.findKey(Exiv2::XmpKey(dt_xmp_keys[i]));
343
344 while(pos != xmp.end())
345 {
346 std::string key = pos->key();
347 const char *ckey = key.c_str();
348 size_t len = key.size();
349 // stop iterating once the key no longer matches what we are trying to delete. this assumes sorted input
350 if(!(g_str_has_prefix(ckey, dt_xmp_keys[i]) && (ckey[len] == '[' || ckey[len] == '\0')))
351 break;
352 pos = xmp.erase(pos);
353 }
354 }
355 }
356
dt_remove_exif_keys(Exiv2::ExifData & exif,const char * keys[],unsigned int n_keys)357 static void dt_remove_exif_keys(Exiv2::ExifData &exif, const char *keys[], unsigned int n_keys)
358 {
359 for(unsigned int i = 0; i < n_keys; i++)
360 {
361 try
362 {
363 Exiv2::ExifData::iterator pos;
364 while((pos = exif.findKey(Exiv2::ExifKey(keys[i]))) != exif.end())
365 exif.erase(pos);
366 }
367 catch(Exiv2::AnyError &e)
368 {
369 // the only exception we may get is "invalid" tag, which is not
370 // important enough to either stop the function, or even display
371 // a message (it's probably the tag is not implemented in the
372 // exiv2 version used)
373 }
374 }
375 }
376
dt_remove_xmp_keys(Exiv2::XmpData & xmp,const char * keys[],unsigned int n_keys)377 static void dt_remove_xmp_keys(Exiv2::XmpData &xmp, const char *keys[], unsigned int n_keys)
378 {
379 for(unsigned int i = 0; i < n_keys; i++)
380 {
381 try
382 {
383 Exiv2::XmpData::iterator pos;
384 while((pos = xmp.findKey(Exiv2::XmpKey(keys[i]))) != xmp.end())
385 xmp.erase(pos);
386 }
387 catch(Exiv2::AnyError &e)
388 {
389 // the only exception we may get is "invalid" tag, which is not
390 // important enough to either stop the function, or even display
391 // a message (it's probably the tag is not implemented in the
392 // exiv2 version used)
393 }
394 }
395 }
396
dt_exif_read_xmp_tag(Exiv2::XmpData & xmpData,Exiv2::XmpData::iterator * pos,string key)397 static bool dt_exif_read_xmp_tag(Exiv2::XmpData &xmpData, Exiv2::XmpData::iterator *pos, string key)
398 {
399 try
400 {
401 return (*pos = xmpData.findKey(Exiv2::XmpKey(key))) != xmpData.end() && (*pos)->size();
402 }
403 catch(Exiv2::AnyError &e)
404 {
405 std::string s(e.what());
406 std::cerr << "[exiv2 read_xmp_tag] " << s << std::endl;
407 return false;
408 }
409 }
410 #define FIND_XMP_TAG(key) dt_exif_read_xmp_tag(xmpData, &pos, key)
411
412 // exiftool (but apparently not exiv2) convert
413 // e.g. "2017:10:23 12:34:56" to "2017-10-23T12:34:54" (ISO)
414 // and some vendors incorrectly use "2017/10/23"
415 // revert this to the format expected by exif and darktable
_sanitize_datetime(char * datetime)416 static void _sanitize_datetime(char *datetime)
417 {
418 // replace 'T' by ' ' (space)
419 char *c;
420 while((c = strchr(datetime, 'T')) != NULL)
421 {
422 *c = ' ';
423 }
424 // replace '-' and '/' by ':'
425 while((c = strchr(datetime, '-')) != NULL || (c = strchr(datetime, '/')) != NULL)
426 {
427 *c = ':';
428 }
429 }
430
431 // FIXME: according to http://www.exiv2.org/doc/classExiv2_1_1Metadatum.html#63c2b87249ba96679c29e01218169124
432 // there is no need to pass xmpData
433 // version = -1 -> version ignored
_exif_decode_xmp_data(dt_image_t * img,Exiv2::XmpData & xmpData,int version,bool exif_read)434 static bool _exif_decode_xmp_data(dt_image_t *img, Exiv2::XmpData &xmpData, int version,
435 bool exif_read)
436 {
437 // as this can be called several times during the image lifetime, clean up first
438 GList *imgs = NULL;
439 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img->id));
440 try
441 {
442 Exiv2::XmpData::iterator pos;
443
444 // older darktable version did not write this data correctly:
445 // the reasoning behind strdup'ing all the strings before passing it to sqlite3 is, that
446 // they are somehow corrupt after the call to sqlite3_prepare_v2() -- don't ask me
447 // why for they don't get passed to that function.
448 if(version == -1 || version > 0)
449 {
450 if(!exif_read) dt_metadata_clear(imgs, FALSE);
451 for(unsigned int i = 0; i < DT_METADATA_NUMBER; i++)
452 {
453 const gchar *key = dt_metadata_get_key(i);
454 if(FIND_XMP_TAG(key))
455 {
456 char *value = strdup(pos->toString().c_str());
457 char *adr = value;
458 // skip any lang="" or charset=xxx
459 while(!strncmp(value, "lang=", 5) || !strncmp(value, "charset=", 8))
460 {
461 while(*value != ' ' && *value) value++;
462 while(*value == ' ') value++;
463 }
464 dt_metadata_set_import(img->id, key, value);
465 free(adr);
466 }
467 }
468 }
469
470 if(FIND_XMP_TAG("Xmp.xmp.Rating"))
471 {
472 const int stars = pos->toLong();
473 dt_image_set_xmp_rating(img, stars);
474 }
475 else
476 dt_image_set_xmp_rating(img, -2);
477
478 if(!exif_read) dt_colorlabels_remove_labels(img->id);
479 if(FIND_XMP_TAG("Xmp.xmp.Label"))
480 {
481 std::string label = pos->toString();
482 if(label == "Red") // Is it really called like that in XMP files?
483 dt_colorlabels_set_label(img->id, 0);
484 else if(label == "Yellow") // Is it really called like that in XMP files?
485 dt_colorlabels_set_label(img->id, 1);
486 else if(label == "Green")
487 dt_colorlabels_set_label(img->id, 2);
488 else if(label == "Blue") // Is it really called like that in XMP files?
489 dt_colorlabels_set_label(img->id, 3);
490 else if(label == "Purple") // Is it really called like that in XMP files?
491 dt_colorlabels_set_label(img->id, 4);
492 }
493 // if Xmp.xmp.Label not managed from an external app use dt colors
494 else if(FIND_XMP_TAG("Xmp.darktable.colorlabels"))
495 {
496 // color labels
497 const int cnt = pos->count();
498 for(int i = 0; i < cnt; i++)
499 {
500 dt_colorlabels_set_label(img->id, pos->toLong(i));
501 }
502 }
503
504 if(dt_conf_get_bool("write_sidecar_files") ||
505 dt_conf_get_bool("ui_last/import_last_tags_imported"))
506 {
507 GList *tags = NULL;
508 // preserve dt tags which are not saved in xmp file
509 if(!exif_read) dt_tag_set_tags(tags, imgs, TRUE, TRUE, FALSE);
510 if(FIND_XMP_TAG("Xmp.lr.hierarchicalSubject"))
511 _exif_import_tags(img, pos);
512 else if(FIND_XMP_TAG("Xmp.dc.subject"))
513 _exif_import_tags(img, pos);
514 }
515
516 /* read gps location */
517 if(FIND_XMP_TAG("Xmp.exif.GPSLatitude"))
518 {
519 img->geoloc.latitude = dt_util_gps_string_to_number(pos->toString().c_str());
520 }
521
522 if(FIND_XMP_TAG("Xmp.exif.GPSLongitude"))
523 {
524 img->geoloc.longitude = dt_util_gps_string_to_number(pos->toString().c_str());
525 }
526
527 if(FIND_XMP_TAG("Xmp.exif.GPSAltitude"))
528 {
529 Exiv2::XmpData::const_iterator ref = xmpData.findKey(Exiv2::XmpKey("Xmp.exif.GPSAltitudeRef"));
530 if(ref != xmpData.end() && ref->size())
531 {
532 std::string sign_str = ref->toString();
533 const char *sign = sign_str.c_str();
534 double elevation = 0.0;
535 if(dt_util_gps_elevation_to_number(pos->toRational(0).first, pos->toRational(0).second, sign[0], &elevation))
536 img->geoloc.elevation = elevation;
537 }
538 }
539
540 /* read lens type from Xmp.exifEX.LensModel */
541 if(FIND_XMP_TAG("Xmp.exifEX.LensModel"))
542 {
543 // lens model
544 char *lens = strdup(pos->toString().c_str());
545 char *adr = lens;
546 if(strncmp(lens, "lang=", 5) == 0)
547 {
548 lens = strchr(lens, ' ');
549 if(lens != NULL) lens++;
550 }
551 // no need to do any Unicode<->locale conversion, the field is specified as ASCII
552 g_strlcpy(img->exif_lens, lens, sizeof(img->exif_lens));
553 free(adr);
554 }
555
556 /* read timestamp from Xmp.exif.DateTimeOriginal */
557 if(FIND_XMP_TAG("Xmp.exif.DateTimeOriginal"))
558 {
559 char *datetime = strdup(pos->toString().c_str());
560 _sanitize_datetime(datetime);
561 g_strlcpy(img->exif_datetime_taken, datetime, sizeof(img->exif_datetime_taken));
562 free(datetime);
563 }
564
565 if(imgs) g_list_free(imgs);
566 imgs = NULL;
567 return true;
568 }
569 catch(Exiv2::AnyError &e)
570 {
571 if(imgs) g_list_free(imgs);
572 imgs = NULL;
573 std::string s(e.what());
574 std::cerr << "[exiv2 _exif_decode_xmp_data] " << img->filename << ": " << s << std::endl;
575 return false;
576 }
577 }
578
dt_exif_read_iptc_tag(Exiv2::IptcData & iptcData,Exiv2::IptcData::const_iterator * pos,string key)579 static bool dt_exif_read_iptc_tag(Exiv2::IptcData &iptcData, Exiv2::IptcData::const_iterator *pos, string key)
580 {
581 try
582 {
583 return (*pos = iptcData.findKey(Exiv2::IptcKey(key))) != iptcData.end() && (*pos)->size();
584 }
585 catch(Exiv2::AnyError &e)
586 {
587 std::string s(e.what());
588 std::cerr << "[exiv2 read_iptc_tag] " << s << std::endl;
589 return false;
590 }
591 }
592 #define FIND_IPTC_TAG(key) dt_exif_read_iptc_tag(iptcData, &pos, key)
593
594
595 // FIXME: according to http://www.exiv2.org/doc/classExiv2_1_1Metadatum.html#63c2b87249ba96679c29e01218169124
596 // there is no need to pass iptcData
_exif_decode_iptc_data(dt_image_t * img,Exiv2::IptcData & iptcData)597 static bool _exif_decode_iptc_data(dt_image_t *img, Exiv2::IptcData &iptcData)
598 {
599 try
600 {
601 Exiv2::IptcData::const_iterator pos;
602 iptcData.sortByKey(); // this helps to quickly find all Iptc.Application2.Keywords
603
604 if((pos = iptcData.findKey(Exiv2::IptcKey("Iptc.Application2.Keywords"))) != iptcData.end())
605 {
606 while(pos != iptcData.end())
607 {
608 std::string key = pos->key();
609 if(g_strcmp0(key.c_str(), "Iptc.Application2.Keywords")) break;
610 std::string str = pos->print();
611 char *tag = dt_util_foo_to_utf8(str.c_str());
612 guint tagid = 0;
613 dt_tag_new(tag, &tagid);
614 dt_tag_attach(tagid, img->id, FALSE, FALSE);
615 g_free(tag);
616 ++pos;
617 }
618 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
619 }
620 if(FIND_IPTC_TAG("Iptc.Application2.Caption"))
621 {
622 std::string str = pos->print(/*&iptcData*/);
623 dt_metadata_set_import(img->id, "Xmp.dc.description", str.c_str());
624 }
625 if(FIND_IPTC_TAG("Iptc.Application2.Copyright"))
626 {
627 std::string str = pos->print(/*&iptcData*/);
628 dt_metadata_set_import(img->id, "Xmp.dc.rights", str.c_str());
629 }
630 if(FIND_IPTC_TAG("Iptc.Application2.Writer"))
631 {
632 std::string str = pos->print(/*&iptcData*/);
633 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
634 }
635 else if(FIND_IPTC_TAG("Iptc.Application2.Contact"))
636 {
637 std::string str = pos->print(/*&iptcData*/);
638 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
639 }
640
641 return true;
642 }
643 catch(Exiv2::AnyError &e)
644 {
645 std::string s(e.what());
646 std::cerr << "[exiv2 _exif_decode_iptc_data] " << img->filename << ": " << s << std::endl;
647 return false;
648 }
649 }
650
651 // Support DefaultUserCrop, what is the safe exif tag?
652 // Magic-nr taken from dng specs, the specs also say it has 4 floats (top,left,bottom,right
653 // We only take them if a) we find a value != the default *and* b) data are plausible
dt_check_usercrop(Exiv2::ExifData & exifData,dt_image_t * img)654 static bool dt_check_usercrop(Exiv2::ExifData &exifData, dt_image_t *img)
655 {
656 Exiv2::ExifData::const_iterator pos = exifData.findKey(Exiv2::ExifKey("Exif.SubImage1.0xc7b5"));
657 if(pos != exifData.end() && pos->count() == 4 && pos->size())
658 {
659 float crop[4];
660 for(int i = 0; i < 4; i++) crop[i] = pos->toFloat(i);
661 if (((crop[0]>0)||(crop[1]>0)||(crop[2]<1)||(crop[3]<1))&&(crop[2]-crop[0]>0.05f)&&(crop[3]-crop[1]>0.05f))
662 {
663 for (int i=0; i<4; i++) img->usercrop[i] = crop[i];
664 return TRUE;
665 }
666 }
667 return FALSE;
668 }
669
dt_exif_img_check_usercrop(dt_image_t * img,const char * filename)670 void dt_exif_img_check_usercrop(dt_image_t *img, const char *filename)
671 {
672 try
673 {
674 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
675 assert(image.get() != 0);
676 read_metadata_threadsafe(image);
677 Exiv2::ExifData &exifData = image->exifData();
678 if(!exifData.empty()) dt_check_usercrop(exifData, img);
679 return;
680 }
681 catch(Exiv2::AnyError &e)
682 {
683 std::string s(e.what());
684 std::cerr << "[exiv2 reading DefaultUserCrop] " << filename << ": " << s << std::endl;
685 return;
686 }
687 }
688
dt_exif_read_exif_tag(Exiv2::ExifData & exifData,Exiv2::ExifData::const_iterator * pos,string key)689 static bool dt_exif_read_exif_tag(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator *pos, string key)
690 {
691 try
692 {
693 return (*pos = exifData.findKey(Exiv2::ExifKey(key))) != exifData.end() && (*pos)->size();
694 }
695 catch(Exiv2::AnyError &e)
696 {
697 std::string s(e.what());
698 std::cerr << "[exiv2 read_exif_tag] " << s << std::endl;
699 return false;
700 }
701 }
702 #define FIND_EXIF_TAG(key) dt_exif_read_exif_tag(exifData, &pos, key)
703
_find_datetime_taken(Exiv2::ExifData & exifData,Exiv2::ExifData::const_iterator pos,char * exif_datetime_taken)704 static void _find_datetime_taken(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos,
705 char *exif_datetime_taken)
706 {
707 if((FIND_EXIF_TAG("Exif.Image.DateTimeOriginal") || FIND_EXIF_TAG("Exif.Photo.DateTimeOriginal"))
708 && pos->size() == DT_DATETIME_LENGTH)
709 {
710 dt_strlcpy_to_utf8(exif_datetime_taken, DT_DATETIME_LENGTH, pos, exifData);
711 _sanitize_datetime(exif_datetime_taken);
712 }
713 else
714 {
715 *exif_datetime_taken = '\0';
716 }
717 }
718
_exif_decode_exif_data(dt_image_t * img,Exiv2::ExifData & exifData)719 static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData)
720 {
721 try
722 {
723 /* List of tag names taken from exiv2's printSummary() in actions.cpp */
724 Exiv2::ExifData::const_iterator pos;
725
726 // look for maker & model first so we can use that info later
727 if(FIND_EXIF_TAG("Exif.Image.Make"))
728 {
729 dt_strlcpy_to_utf8(img->exif_maker, sizeof(img->exif_maker), pos, exifData);
730 }
731 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Make"))
732 {
733 dt_strlcpy_to_utf8(img->exif_maker, sizeof(img->exif_maker), pos, exifData);
734 }
735
736 for(char *c = img->exif_maker + sizeof(img->exif_maker) - 1; c > img->exif_maker; c--)
737 if(*c != ' ' && *c != '\0')
738 {
739 *(c + 1) = '\0';
740 break;
741 }
742
743 if(FIND_EXIF_TAG("Exif.Image.Model"))
744 {
745 dt_strlcpy_to_utf8(img->exif_model, sizeof(img->exif_model), pos, exifData);
746 }
747 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Model"))
748 {
749 dt_strlcpy_to_utf8(img->exif_model, sizeof(img->exif_model), pos, exifData);
750 }
751
752 for(char *c = img->exif_model + sizeof(img->exif_model) - 1; c > img->exif_model; c--)
753 if(*c != ' ' && *c != '\0')
754 {
755 *(c + 1) = '\0';
756 break;
757 }
758
759 // Make sure we copy the exif make and model to the correct place if needed
760 dt_image_refresh_makermodel(img);
761
762 /* Read shutter time */
763 if((pos = Exiv2::exposureTime(exifData)) != exifData.end() && pos->size())
764 {
765 // dt_strlcpy_to_utf8(uf->conf->shutterText, max_name, pos, exifData);
766 img->exif_exposure = pos->toFloat();
767 }
768 else if(FIND_EXIF_TAG("Exif.Photo.ShutterSpeedValue") || FIND_EXIF_TAG("Exif.Image.ShutterSpeedValue"))
769 {
770 // uf_strlcpy_to_utf8(uf->conf->shutterText, max_name, pos, exifData);
771 img->exif_exposure = exp2f(-1.0f * pos->toFloat()); // convert from APEX value
772 }
773
774 // Read exposure bias
775 if(FIND_EXIF_TAG("Exif.Photo.ExposureBiasValue") || FIND_EXIF_TAG("Exif.Image.ExposureBiasValue"))
776 {
777 img->exif_exposure_bias = pos->toFloat();
778 }
779
780 /* Read aperture */
781 if((pos = Exiv2::fNumber(exifData)) != exifData.end() && pos->size())
782 {
783 img->exif_aperture = pos->toFloat();
784 }
785 else if(FIND_EXIF_TAG("Exif.Photo.ApertureValue") || FIND_EXIF_TAG("Exif.Image.ApertureValue"))
786 {
787 img->exif_aperture = exp2f(pos->toFloat() / 2.0f); // convert from APEX value
788 }
789
790 /* Read ISO speed - Nikon happens to return a pair for Lo and Hi modes */
791 if((pos = Exiv2::isoSpeed(exifData)) != exifData.end() && pos->size())
792 {
793 // if standard exif iso tag, use the old way of interpreting the return value to be more regression-save
794 if(strcmp(pos->key().c_str(), "Exif.Photo.ISOSpeedRatings") == 0)
795 {
796 int isofield = pos->count() > 1 ? 1 : 0;
797 img->exif_iso = pos->toFloat(isofield);
798 }
799 else
800 {
801 std::string str = pos->print();
802 img->exif_iso = (float)std::atof(str.c_str());
803 }
804 }
805 // some newer cameras support iso settings that exceed the 16 bit of exif's ISOSpeedRatings
806 if(img->exif_iso == 65535 || img->exif_iso == 0)
807 {
808 if(FIND_EXIF_TAG("Exif.PentaxDng.ISO") || FIND_EXIF_TAG("Exif.Pentax.ISO"))
809 {
810 std::string str = pos->print();
811 img->exif_iso = (float)std::atof(str.c_str());
812 }
813 else if((!g_strcmp0(img->exif_maker, "SONY") || !g_strcmp0(img->exif_maker, "Canon"))
814 && FIND_EXIF_TAG("Exif.Photo.RecommendedExposureIndex"))
815 {
816 img->exif_iso = pos->toFloat();
817 }
818 }
819
820 /* Read focal length */
821 if((pos = Exiv2::focalLength(exifData)) != exifData.end() && pos->size())
822 {
823 // This works around a bug in exiv2 the developers refuse to fix
824 // For details see http://dev.exiv2.org/issues/1083
825 if (pos->key() == "Exif.Canon.FocalLength" && pos->count() == 4)
826 img->exif_focal_length = pos->toFloat(1);
827 else
828 img->exif_focal_length = pos->toFloat();
829 }
830
831 /* Read focal length in 35mm if available and try to calculate crop factor */
832 if(FIND_EXIF_TAG("Exif.Photo.FocalLengthIn35mmFilm"))
833 {
834 const float focal_length_35mm = pos->toFloat();
835 if(focal_length_35mm > 0.0f && img->exif_focal_length > 0.0f)
836 img->exif_crop = focal_length_35mm / img->exif_focal_length;
837 else
838 img->exif_crop = 1.0f;
839 }
840
841 if (dt_check_usercrop(exifData, img))
842 {
843 img->flags |= DT_IMAGE_HAS_USERCROP;
844 guint tagid = 0;
845 char tagname[64];
846 snprintf(tagname, sizeof(tagname), "darktable|mode|exif-crop");
847 dt_tag_new(tagname, &tagid);
848 dt_tag_attach(tagid, img->id, FALSE, FALSE);
849 }
850 /*
851 * Get the focus distance in meters.
852 */
853 if(FIND_EXIF_TAG("Exif.NikonLd2.FocusDistance"))
854 {
855 float value = pos->toFloat();
856 img->exif_focus_distance = (0.01 * pow(10, value / 40));
857 }
858 else if(FIND_EXIF_TAG("Exif.NikonLd3.FocusDistance"))
859 {
860 float value = pos->toFloat();
861 img->exif_focus_distance = (0.01 * pow(10, value / 40));
862 }
863 else if(FIND_EXIF_TAG("Exif.OlympusFi.FocusDistance"))
864 {
865 /* the distance is stored as a rational (fraction). according to
866 * http://www.dpreview.com/forums/thread/1173960?page=4
867 * some Olympus cameras have a wrong denominator of 10 in there while the nominator is always in mm.
868 * thus we ignore the denominator
869 * and divide with 1000.
870 * "I've checked a number of E-1 and E-300 images, and I agree that the FocusDistance looks like it is
871 * in mm for the E-1. However,
872 * it looks more like cm for the E-300.
873 * For both cameras, this value is stored as a rational. With the E-1, the denominator is always 1,
874 * while for the E-300 it is 10.
875 * Therefore, it looks like the numerator in both cases is in mm (which makes a bit of sense, in an odd
876 * sort of way). So I think
877 * what I will do in ExifTool is to take the numerator and divide by 1000 to display the focus distance
878 * in meters."
879 * -- Boardhead, dpreview forums in 2005
880 */
881 int nominator = pos->toRational(0).first;
882 img->exif_focus_distance = fmax(0.0, (0.001 * nominator));
883 }
884 else if(EXIV2_MAKE_VERSION(0,25,0) <= Exiv2::versionNumber() && FIND_EXIF_TAG("Exif.CanonFi.FocusDistanceUpper"))
885 {
886 const float FocusDistanceUpper = pos->toFloat();
887 if(FocusDistanceUpper <= 0.0f || (int)FocusDistanceUpper >= 0xffff)
888 {
889 img->exif_focus_distance = 0.0f;
890 }
891 else
892 {
893 img->exif_focus_distance = FocusDistanceUpper / 100.0;
894 if(FIND_EXIF_TAG("Exif.CanonFi.FocusDistanceLower"))
895 {
896 const float FocusDistanceLower = pos->toFloat();
897 if(FocusDistanceLower > 0.0f && (int)FocusDistanceLower < 0xffff)
898 {
899 img->exif_focus_distance += FocusDistanceLower / 100.0;
900 img->exif_focus_distance /= 2.0;
901 }
902 }
903 }
904 }
905 else if(FIND_EXIF_TAG("Exif.CanonSi.SubjectDistance"))
906 {
907 img->exif_focus_distance = pos->toFloat() / 100.0;
908 }
909 else if((pos = Exiv2::subjectDistance(exifData)) != exifData.end() && pos->size())
910 {
911 img->exif_focus_distance = pos->toFloat();
912 }
913 else if(Exiv2::testVersion(0,27,2) && FIND_EXIF_TAG("Exif.Sony2Fp.FocusPosition2"))
914 {
915 const float focus_position = pos->toFloat();
916
917 if (focus_position && FIND_EXIF_TAG("Exif.Photo.FocalLengthIn35mmFilm")) {
918 const float focal_length_35mm = pos->toFloat();
919
920 /* http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3688.msg29653.html#msg29653 */
921 img->exif_focus_distance = (pow(2, focus_position / 16 - 5) + 1) * focal_length_35mm / 1000;
922 }
923 }
924
925 /*
926 * Read image orientation
927 */
928 if(FIND_EXIF_TAG("Exif.Image.Orientation"))
929 {
930 img->orientation = dt_image_orientation_to_flip_bits(pos->toLong());
931 }
932 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Orientation"))
933 {
934 img->orientation = dt_image_orientation_to_flip_bits(pos->toLong());
935 }
936
937 /* read gps location */
938 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSLatitude"))
939 {
940 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSLatitudeRef"));
941 if(ref != exifData.end() && ref->size() && pos->count() == 3)
942 {
943 std::string sign_str = ref->toString();
944 const char *sign = sign_str.c_str();
945 double latitude = 0.0;
946 if(dt_util_gps_rationale_to_number(pos->toRational(0).first, pos->toRational(0).second,
947 pos->toRational(1).first, pos->toRational(1).second,
948 pos->toRational(2).first, pos->toRational(2).second, sign[0], &latitude))
949 img->geoloc.latitude = latitude;
950 }
951 }
952
953 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSLongitude"))
954 {
955 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSLongitudeRef"));
956 if(ref != exifData.end() && ref->size() && pos->count() == 3)
957 {
958 std::string sign_str = ref->toString();
959 const char *sign = sign_str.c_str();
960 double longitude = 0.0;
961 if(dt_util_gps_rationale_to_number(pos->toRational(0).first, pos->toRational(0).second,
962 pos->toRational(1).first, pos->toRational(1).second,
963 pos->toRational(2).first, pos->toRational(2).second, sign[0], &longitude))
964 img->geoloc.longitude = longitude;
965 }
966 }
967
968 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSAltitude"))
969 {
970 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSAltitudeRef"));
971 if(ref != exifData.end() && ref->size())
972 {
973 std::string sign_str = ref->toString();
974 const char *sign = sign_str.c_str();
975 double elevation = 0.0;
976 if(dt_util_gps_elevation_to_number(pos->toRational(0).first, pos->toRational(0).second, sign[0], &elevation))
977 img->geoloc.elevation = elevation;
978 }
979 }
980
981 /* Read lens name */
982 if((FIND_EXIF_TAG("Exif.CanonCs.LensType")
983 && pos->print(&exifData) != "(0)"
984 && pos->print(&exifData) != "(65535)")
985 || FIND_EXIF_TAG("Exif.Canon.0x0095"))
986 {
987 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
988 }
989 else if(EXIV2_MAKE_VERSION(0,25,0) <= Exiv2::versionNumber() && FIND_EXIF_TAG("Exif.PentaxDng.LensType"))
990 {
991 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
992 }
993 else if(FIND_EXIF_TAG("Exif.Panasonic.LensType"))
994 {
995 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
996 }
997 else if(FIND_EXIF_TAG("Exif.OlympusEq.LensType"))
998 {
999 /* For every Olympus camera Exif.OlympusEq.LensType is present. */
1000 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1001
1002 /* We have to check if Exif.OlympusEq.LensType has been translated by
1003 * exiv2. If it hasn't, fall back to Exif.OlympusEq.LensModel. */
1004 std::string lens(img->exif_lens);
1005 if(std::string::npos == lens.find_first_not_of(" 1234567890"))
1006 {
1007 /* Exif.OlympusEq.LensType contains only digits and spaces.
1008 * This means that exiv2 couldn't convert it to human readable
1009 * form. */
1010 if(FIND_EXIF_TAG("Exif.OlympusEq.LensModel"))
1011 {
1012 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1013 }
1014 /* Just in case Exif.OlympusEq.LensModel hasn't been found */
1015 else if(FIND_EXIF_TAG("Exif.Photo.LensModel"))
1016 {
1017 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1018 }
1019 fprintf(stderr, "[exif] Warning: lens \"%s\" unknown as \"%s\"\n", img->exif_lens, lens.c_str());
1020 }
1021 }
1022 else if((pos = Exiv2::lensName(exifData)) != exifData.end() && pos->size())
1023 {
1024 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1025 }
1026
1027 // finally the lens has only numbers and parentheses, let's try to use
1028 // Exif.Photo.LensModel if defined.
1029
1030 std::string lens(img->exif_lens);
1031 if(std::string::npos == lens.find_first_not_of(" (1234567890)")
1032 && FIND_EXIF_TAG("Exif.Photo.LensModel"))
1033 {
1034 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1035 }
1036
1037 #if 0
1038 /* Read flash mode */
1039 if ( (pos=exifData.findKey(Exiv2::ExifKey("Exif.Photo.Flash")))
1040 != exifData.end() && pos->size())
1041 {
1042 uf_strlcpy_to_utf8(uf->conf->flashText, max_name, pos, exifData);
1043 }
1044 /* Read White Balance Setting */
1045 if ( (pos=exifData.findKey(Exiv2::ExifKey("Exif.Photo.WhiteBalance")))
1046 != exifData.end() && pos->size())
1047 {
1048 uf_strlcpy_to_utf8(uf->conf->whiteBalanceText, max_name, pos, exifData);
1049 }
1050 #endif
1051
1052 _find_datetime_taken(exifData, pos, img->exif_datetime_taken);
1053
1054 if(FIND_EXIF_TAG("Exif.Image.Artist"))
1055 {
1056 std::string str = pos->print(&exifData);
1057 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
1058 }
1059 else if(FIND_EXIF_TAG("Exif.Canon.OwnerName"))
1060 {
1061 std::string str = pos->print(&exifData);
1062 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
1063 }
1064
1065 // FIXME: Should the UserComment go into the description? Or do we need an extra field for this?
1066 if(FIND_EXIF_TAG("Exif.Photo.UserComment"))
1067 {
1068 std::string str = pos->print(&exifData);
1069 Exiv2::CommentValue value(str);
1070 std::string str2 = value.comment();
1071 if(str2 != "binary comment")
1072 dt_metadata_set_import(img->id, "Xmp.dc.description", str2.c_str());
1073 }
1074
1075 if(FIND_EXIF_TAG("Exif.Image.Copyright"))
1076 {
1077 std::string str = pos->print(&exifData);
1078 dt_metadata_set_import(img->id, "Xmp.dc.rights", str.c_str());
1079 }
1080
1081 if(FIND_EXIF_TAG("Exif.Image.Rating"))
1082 {
1083 const int stars = pos->toLong();
1084 dt_image_set_xmp_rating(img, stars);
1085 }
1086 else if(FIND_EXIF_TAG("Exif.Image.RatingPercent"))
1087 {
1088 const int stars = pos->toLong() * 5. / 100;
1089 dt_image_set_xmp_rating(img, stars);
1090 }
1091 else
1092 dt_image_set_xmp_rating(img, -2);
1093
1094 // read embedded color matrix as used in DNGs
1095 {
1096 int illu1 = -1, illu2 = -1, illu = -1; // -1: not found, otherwise the detected CalibrationIlluminant
1097 float colmatrix[12];
1098 img->d65_color_matrix[0] = NAN; // make sure for later testing
1099 // The correction matrices are taken from
1100 // http://www.brucelindbloom.com - chromatic Adaption.
1101 // using Bradford method: found Illuminant -> D65
1102 const float correctmat[7][9] = {
1103 { 0.9555766, -0.0230393, 0.0631636, -0.0282895, 1.0099416, 0.0210077, 0.0122982, -0.0204830,
1104 1.3299098 }, // 23 = D50
1105 { 0.9726856, -0.0135482, 0.0361731, -0.0167463, 1.0049102, 0.0120598, 0.0070026, -0.0116372,
1106 1.1869548 }, // 20 = D55
1107 { 1.0206905, 0.0091588, -0.0228796, 0.0115005, 0.9984917, -0.0076762, -0.0043619, 0.0072053,
1108 0.8853432 }, // 22 = D75
1109 { 0.8446965, -0.1179225, 0.3948108, -0.1366303, 1.1041226, 0.1291718, 0.0798489, -0.1348999,
1110 3.1924009 }, // 17 = Standard light A
1111 { 0.9415037, -0.0321240, 0.0584672, -0.0428238, 1.0250998, 0.0203309, 0.0101511, -0.0161170,
1112 1.2847354 }, // 18 = Standard light B
1113 { 0.9904476, -0.0071683, -0.0116156, -0.0123712, 1.0155950, -0.0029282, -0.0035635, 0.0067697,
1114 0.9181569 }, // 19 = Standard light C
1115 { 0.9212269, -0.0449128, 0.1211620, -0.0553723, 1.0277243, 0.0403563, 0.0235086, -0.0391019,
1116 1.6390644 } // F2 = cool white
1117 };
1118
1119 if(FIND_EXIF_TAG("Exif.Image.CalibrationIlluminant1")) illu1 = pos->toLong();
1120 if(FIND_EXIF_TAG("Exif.Image.CalibrationIlluminant2")) illu2 = pos->toLong();
1121 Exiv2::ExifData::const_iterator cm1_pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.ColorMatrix1"));
1122 Exiv2::ExifData::const_iterator cm2_pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.ColorMatrix2"));
1123
1124 // Which is the wanted colormatrix?
1125 // If we have D65 in Illuminant1 we use it; otherwise we prefer Illuminant2 because it's the higher
1126 // color temperature and thus closer to D65
1127 if(illu1 == 21 && cm1_pos != exifData.end() && cm1_pos->count() == 9 && cm1_pos->size())
1128 {
1129 for(int i = 0; i < 9; i++) colmatrix[i] = cm1_pos->toFloat(i);
1130 illu = illu1;
1131 }
1132 else if(illu2 != -1 && cm2_pos != exifData.end() && cm2_pos->count() == 9 && cm2_pos->size())
1133 {
1134 for(int i = 0; i < 9; i++) colmatrix[i] = cm2_pos->toFloat(i);
1135 illu = illu2;
1136 }
1137 else if(illu1 != -1 && cm1_pos != exifData.end() && cm1_pos->count() == 9 && cm1_pos->size())
1138 {
1139 for(int i = 0; i < 9; i++) colmatrix[i] = cm1_pos->toFloat(i);
1140 illu = illu1;
1141 }
1142 // In a few cases we only have one color matrix; it should not be corrected
1143 if(illu == -1 && cm1_pos != exifData.end() && cm1_pos->count() == 9 && cm1_pos->size())
1144 {
1145 for(int i = 0; i < 9; i++) colmatrix[i] = cm1_pos->toFloat(i);
1146 illu = 0;
1147 }
1148
1149
1150 // Take the found CalibrationIlluminant / ColorMatrix pair.
1151 // D65 or default: just copy. Otherwise multiply by the specific correction matrix.
1152 if(illu != -1)
1153 {
1154 // If no supported Illuminant is found it's better NOT to use the found matrix.
1155 // The colorin module will write an error message and use a fallback matrix
1156 // instead of showing wrong colors.
1157 switch(illu)
1158 {
1159 case 23:
1160 mat3mul(img->d65_color_matrix, correctmat[0], colmatrix);
1161 break;
1162 case 20:
1163 mat3mul(img->d65_color_matrix, correctmat[1], colmatrix);
1164 break;
1165 case 22:
1166 mat3mul(img->d65_color_matrix, correctmat[2], colmatrix);
1167 break;
1168 case 17:
1169 mat3mul(img->d65_color_matrix, correctmat[3], colmatrix);
1170 break;
1171 case 18:
1172 mat3mul(img->d65_color_matrix, correctmat[4], colmatrix);
1173 break;
1174 case 19:
1175 mat3mul(img->d65_color_matrix, correctmat[5], colmatrix);
1176 break;
1177 case 3:
1178 mat3mul(img->d65_color_matrix, correctmat[3], colmatrix);
1179 break;
1180 case 14:
1181 mat3mul(img->d65_color_matrix, correctmat[6], colmatrix);
1182 break;
1183 default:
1184 for(int i = 0; i < 9; i++) img->d65_color_matrix[i] = colmatrix[i];
1185 break;
1186 }
1187 // Maybe there is a predefined camera matrix in adobe_coeff?
1188 // This is tested to possibly override the matrix.
1189 colmatrix[0] = NAN;
1190 dt_dcraw_adobe_coeff(img->camera_model, (float(*)[12])colmatrix);
1191 if(!isnan(colmatrix[0]))
1192 for(int i = 0; i < 9; i++) img->d65_color_matrix[i] = colmatrix[i];
1193 }
1194 }
1195
1196 int is_monochrome = FALSE;
1197 int is_hdr = dt_image_is_hdr(img);
1198
1199 // Finding out about DNG hdr and monochrome images can be done here while reading exif data.
1200 if(FIND_EXIF_TAG("Exif.Image.DNGVersion"))
1201 {
1202 int format = 1;
1203 int bps = 0;
1204 int spp = 0;
1205 int phi = 0;
1206
1207 if(FIND_EXIF_TAG("Exif.SubImage1.SampleFormat"))
1208 format = pos->toLong();
1209 else if(FIND_EXIF_TAG("Exif.Image.SampleFormat"))
1210 format = pos->toLong();
1211
1212 if(FIND_EXIF_TAG("Exif.SubImage1.BitsPerSample"))
1213 bps = pos->toLong();
1214
1215 if(FIND_EXIF_TAG("Exif.SubImage1.SamplesPerPixel"))
1216 spp = pos->toLong();
1217
1218 if(FIND_EXIF_TAG("Exif.SubImage1.PhotometricInterpretation"))
1219 phi = pos->toLong();
1220
1221 if((format == 3) && (bps >= 16) && (((spp == 1) && (phi == 32803)) || ((spp == 3) && (phi == 34892)))) is_hdr = TRUE;
1222 if((format == 1) && (bps == 16) && (spp == 1) && (phi == 34892)) is_monochrome = TRUE;
1223 }
1224
1225 if(is_hdr)
1226 dt_imageio_set_hdr_tag(img);
1227
1228 if(is_monochrome)
1229 {
1230 img->flags |= DT_IMAGE_MONOCHROME;
1231 dt_imageio_update_monochrome_workflow_tag(img->id, DT_IMAGE_MONOCHROME);
1232 }
1233 // some files have the colorspace explicitly set. try to read that.
1234 // is_ldr -> none
1235 // 0x01 -> sRGB
1236 // 0x02 -> AdobeRGB
1237 // 0xffff -> Uncalibrated
1238 // + Exif.Iop.InteroperabilityIndex of 'R03' -> AdobeRGB
1239 // + Exif.Iop.InteroperabilityIndex of 'R98' -> sRGB
1240 if(dt_image_is_ldr(img) && FIND_EXIF_TAG("Exif.Photo.ColorSpace"))
1241 {
1242 int colorspace = pos->toLong();
1243 if(colorspace == 0x01)
1244 img->colorspace = DT_IMAGE_COLORSPACE_SRGB;
1245 else if(colorspace == 0x02)
1246 img->colorspace = DT_IMAGE_COLORSPACE_ADOBE_RGB;
1247 else if(colorspace == 0xffff)
1248 {
1249 if(FIND_EXIF_TAG("Exif.Iop.InteroperabilityIndex"))
1250 {
1251 std::string interop_index = pos->toString();
1252 if(interop_index == "R03")
1253 img->colorspace = DT_IMAGE_COLORSPACE_ADOBE_RGB;
1254 else if(interop_index == "R98")
1255 img->colorspace = DT_IMAGE_COLORSPACE_SRGB;
1256 }
1257 }
1258 }
1259
1260 #if EXIV2_MINOR_VERSION < 23
1261 // workaround for an exiv2 bug writing random garbage into exif_lens for this camera:
1262 // http://dev.exiv2.org/issues/779
1263 if(!strcmp(img->exif_model, "DMC-GH2")) snprintf(img->exif_lens, sizeof(img->exif_lens), "(unknown)");
1264 #endif
1265
1266 // Improve lens detection for Sony SAL lenses.
1267 if(FIND_EXIF_TAG("Exif.Sony2.LensID") && pos->toLong() != 65535 && pos->print().find('|') == std::string::npos)
1268 {
1269 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1270 }
1271 // Workaround for an issue on newer Sony NEX cams.
1272 // The default EXIF field is not used by Sony to store lens data
1273 // http://dev.exiv2.org/issues/883
1274 // http://darktable.org/redmine/issues/8813
1275 // FIXME: This is still a workaround
1276 else if((!strncmp(img->exif_model, "NEX", 3)) || (!strncmp(img->exif_model, "ILCE", 4)))
1277 {
1278 snprintf(img->exif_lens, sizeof(img->exif_lens), "(unknown)");
1279 if(FIND_EXIF_TAG("Exif.Photo.LensModel"))
1280 {
1281 std::string str = pos->print(&exifData);
1282 snprintf(img->exif_lens, sizeof(img->exif_lens), "%s", str.c_str());
1283 }
1284 };
1285
1286 img->exif_inited = 1;
1287 return true;
1288 }
1289 catch(Exiv2::AnyError &e)
1290 {
1291 std::string s(e.what());
1292 std::cerr << "[exiv2 _exif_decode_exif_data] " << img->filename << ": " << s << std::endl;
1293 return false;
1294 }
1295 }
1296
dt_exif_apply_default_metadata(dt_image_t * img)1297 void dt_exif_apply_default_metadata(dt_image_t *img)
1298 {
1299 if(dt_conf_get_bool("ui_last/import_apply_metadata") == TRUE)
1300 {
1301 char *str;
1302
1303 for(unsigned int i = 0; i < DT_METADATA_NUMBER; i++)
1304 {
1305 if(dt_metadata_get_type(i) != DT_METADATA_TYPE_INTERNAL)
1306 {
1307 const char *name = dt_metadata_get_name(i);
1308 char *setting = dt_util_dstrcat(NULL, "plugins/lighttable/metadata/%s_flag", name);
1309 const gboolean hidden = dt_conf_get_int(setting) & DT_METADATA_FLAG_HIDDEN;
1310 g_free(setting);
1311 // don't import hidden stuff
1312 if(!hidden)
1313 {
1314 setting = dt_util_dstrcat(NULL, "ui_last/import_last_%s", name);
1315 str = dt_conf_get_string(setting);
1316 if(str && str[0])
1317 {
1318 // calculated metadata
1319 dt_variables_params_t *params;
1320 dt_variables_params_init(¶ms);
1321 params->filename = img->filename;
1322 params->jobcode = "import";
1323 params->sequence = 0;
1324 params->imgid = img->id;
1325 params->img = (void *)img;
1326 // at this time only exif info are available
1327 gchar *result = dt_variables_expand(params, str, FALSE);
1328 if(result && result[0])
1329 {
1330 g_free(str);
1331 str = result;
1332 }
1333 dt_metadata_set(img->id, dt_metadata_get_key(i), str, FALSE);
1334 g_free(str);
1335 }
1336 g_free(setting);
1337 }
1338 }
1339 }
1340
1341 str = dt_conf_get_string("ui_last/import_last_tags");
1342 if(img->id > 0 && str != NULL && str[0] != '\0')
1343 {
1344 GList *imgs = NULL;
1345 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img->id));
1346 dt_tag_attach_string_list(str, imgs, FALSE);
1347 g_list_free(imgs);
1348 }
1349 g_free(str);
1350 }
1351 }
1352
1353 // TODO: can this blob also contain xmp and iptc data?
dt_exif_read_from_blob(dt_image_t * img,uint8_t * blob,const int size)1354 int dt_exif_read_from_blob(dt_image_t *img, uint8_t *blob, const int size)
1355 {
1356 try
1357 {
1358 Exiv2::ExifData exifData;
1359 Exiv2::ExifParser::decode(exifData, blob, size);
1360 bool res = _exif_decode_exif_data(img, exifData);
1361 dt_exif_apply_default_metadata(img);
1362 return res ? 0 : 1;
1363 }
1364 catch(Exiv2::AnyError &e)
1365 {
1366 std::string s(e.what());
1367 std::cerr << "[exiv2 dt_exif_read_from_blob] " << img->filename << ": " << s << std::endl;
1368 return 1;
1369 }
1370 }
1371
1372 /**
1373 * Get the largest possible thumbnail from the image
1374 */
dt_exif_get_thumbnail(const char * path,uint8_t ** buffer,size_t * size,char ** mime_type)1375 int dt_exif_get_thumbnail(const char *path, uint8_t **buffer, size_t *size, char **mime_type)
1376 {
1377 try
1378 {
1379 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
1380 assert(image.get() != 0);
1381 read_metadata_threadsafe(image);
1382
1383 // Get a list of preview images available in the image. The list is sorted
1384 // by the preview image pixel size, starting with the smallest preview.
1385 Exiv2::PreviewManager loader(*image);
1386 Exiv2::PreviewPropertiesList list = loader.getPreviewProperties();
1387 if(list.empty())
1388 {
1389 dt_print(DT_DEBUG_LIGHTTABLE, "[exiv2 dt_exif_get_thumbnail] couldn't find thumbnail for %s", path);
1390 return 1;
1391 }
1392
1393 // Select the largest one
1394 // FIXME: We could probably select a smaller thumbnail to match the mip size
1395 // we actually want to create. Is it really much faster though?
1396 Exiv2::PreviewProperties selected = list.back();
1397
1398 // Get the selected preview image
1399 Exiv2::PreviewImage preview = loader.getPreviewImage(selected);
1400 const unsigned char *tmp = preview.pData();
1401 size_t _size = preview.size();
1402
1403 *size = _size;
1404 *mime_type = strdup(preview.mimeType().c_str());
1405 *buffer = (uint8_t *)malloc(_size);
1406 if(!*buffer) {
1407 std::cerr << "[exiv2 dt_exif_get_thumbnail] couldn't allocate memory for thumbnail for " << path << std::endl;
1408 return 1;
1409 }
1410 //std::cerr << "[exiv2] "<< path << ": found thumbnail "<< preview.width() << "x" << preview.height() << std::endl;
1411 memcpy(*buffer, tmp, _size);
1412
1413 return 0;
1414 }
1415 catch(Exiv2::AnyError &e)
1416 {
1417 std::string s(e.what());
1418 std::cerr << "[exiv2 dt_exif_get_thumbnail] " << path << ": " << s << std::endl;
1419 return 1;
1420 }
1421 }
1422
1423 /** read the metadata of an image.
1424 * XMP data trumps IPTC data trumps EXIF data
1425 */
dt_exif_read(dt_image_t * img,const char * path)1426 int dt_exif_read(dt_image_t *img, const char *path)
1427 {
1428 // at least set datetime taken to something useful in case there is no exif data in this file (pfm, png,
1429 // ...)
1430 struct stat statbuf;
1431
1432 if(!stat(path, &statbuf))
1433 {
1434 struct tm result;
1435 strftime(img->exif_datetime_taken, DT_DATETIME_LENGTH, "%Y:%m:%d %H:%M:%S",
1436 localtime_r(&statbuf.st_mtime, &result));
1437 }
1438
1439 try
1440 {
1441 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
1442 assert(image.get() != 0);
1443 read_metadata_threadsafe(image);
1444 bool res = true;
1445
1446 // EXIF metadata
1447 Exiv2::ExifData &exifData = image->exifData();
1448 if(!exifData.empty())
1449 {
1450 res = _exif_decode_exif_data(img, exifData);
1451 if(dt_conf_get_bool("ui/detect_mono_exif"))
1452 {
1453 const int oldflags = dt_image_monochrome_flags(img) | (img->flags & DT_IMAGE_MONOCHROME_WORKFLOW);
1454 if(dt_imageio_has_mono_preview(path))
1455 img->flags |= (DT_IMAGE_MONOCHROME_PREVIEW | DT_IMAGE_MONOCHROME_WORKFLOW);
1456 else
1457 img->flags &= ~(DT_IMAGE_MONOCHROME_PREVIEW | DT_IMAGE_MONOCHROME_WORKFLOW);
1458
1459 if(oldflags != (dt_image_monochrome_flags(img) | (img->flags & DT_IMAGE_MONOCHROME_WORKFLOW)))
1460 dt_imageio_update_monochrome_workflow_tag(img->id, dt_image_monochrome_flags(img));
1461 }
1462 }
1463 else
1464 img->exif_inited = 1;
1465
1466 // these get overwritten by IPTC and XMP. is that how it should work?
1467 dt_exif_apply_default_metadata(img);
1468
1469 // IPTC metadata.
1470 Exiv2::IptcData &iptcData = image->iptcData();
1471 if(!iptcData.empty()) res = _exif_decode_iptc_data(img, iptcData) && res;
1472
1473 // XMP metadata
1474 Exiv2::XmpData &xmpData = image->xmpData();
1475 if(!xmpData.empty())
1476 res = _exif_decode_xmp_data(img, xmpData, -1, true) && res;
1477
1478 // Initialize size - don't wait for full raw to be loaded to get this
1479 // information. If use_embedded_thumbnail is set, it will take a
1480 // change in development history to have this information
1481 img->height = image->pixelHeight();
1482 img->width = image->pixelWidth();
1483
1484 return res ? 0 : 1;
1485 }
1486 catch(Exiv2::AnyError &e)
1487 {
1488 std::string s(e.what());
1489 std::cerr << "[exiv2 dt_exif_read] " << path << ": " << s << std::endl;
1490 return 1;
1491 }
1492 }
1493
dt_exif_write_blob(uint8_t * blob,uint32_t size,const char * path,const int compressed)1494 int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
1495 {
1496 try
1497 {
1498 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
1499 assert(image.get() != 0);
1500 read_metadata_threadsafe(image);
1501 Exiv2::ExifData &imgExifData = image->exifData();
1502 Exiv2::ExifData blobExifData;
1503 Exiv2::ExifParser::decode(blobExifData, blob + 6, size);
1504 Exiv2::ExifData::const_iterator end = blobExifData.end();
1505 Exiv2::ExifData::iterator it;
1506 for(Exiv2::ExifData::const_iterator i = blobExifData.begin(); i != end; ++i)
1507 {
1508 // add() does not override! we need to delete existing key first.
1509 Exiv2::ExifKey key(i->key());
1510 if((it = imgExifData.findKey(key)) != imgExifData.end()) imgExifData.erase(it);
1511
1512 imgExifData.add(Exiv2::ExifKey(i->key()), &i->value());
1513 }
1514
1515 {
1516 // Remove thumbnail
1517 static const char *keys[] = {
1518 "Exif.Thumbnail.Compression",
1519 "Exif.Thumbnail.XResolution",
1520 "Exif.Thumbnail.YResolution",
1521 "Exif.Thumbnail.ResolutionUnit",
1522 "Exif.Thumbnail.JPEGInterchangeFormat",
1523 "Exif.Thumbnail.JPEGInterchangeFormatLength"
1524 };
1525 static const guint n_keys = G_N_ELEMENTS(keys);
1526 dt_remove_exif_keys(imgExifData, keys, n_keys);
1527 }
1528
1529 // only compressed images may set PixelXDimension and PixelYDimension
1530 if(!compressed)
1531 {
1532 static const char *keys[] = {
1533 "Exif.Photo.PixelXDimension",
1534 "Exif.Photo.PixelYDimension"
1535 };
1536 static const guint n_keys = G_N_ELEMENTS(keys);
1537 dt_remove_exif_keys(imgExifData, keys, n_keys);
1538 }
1539
1540 imgExifData.sortByTag();
1541 image->writeMetadata();
1542 }
1543 catch(Exiv2::AnyError &e)
1544 {
1545 std::string s(e.what());
1546 std::cerr << "[exiv2 dt_exif_write_blob] " << path << ": " << s << std::endl;
1547 return 0;
1548 }
1549 return 1;
1550 }
1551
dt_remove_exif_geotag(Exiv2::ExifData & exifData)1552 static void dt_remove_exif_geotag(Exiv2::ExifData &exifData)
1553 {
1554 static const char *keys[] =
1555 {
1556 "Exif.GPSInfo.GPSLatitude",
1557 "Exif.GPSInfo.GPSLongitude",
1558 "Exif.GPSInfo.GPSAltitude",
1559 "Exif.GPSInfo.GPSLatitudeRef",
1560 "Exif.GPSInfo.GPSLongitudeRef",
1561 "Exif.GPSInfo.GPSAltitudeRef",
1562 "Exif.GPSInfo.GPSVersionID"
1563 };
1564 static const guint n_keys = G_N_ELEMENTS(keys);
1565 dt_remove_exif_keys(exifData, keys, n_keys);
1566 }
1567
dt_exif_read_blob(uint8_t ** buf,const char * path,const int imgid,const int sRGB,const int out_width,const int out_height,const int dng_mode)1568 int dt_exif_read_blob(uint8_t **buf, const char *path, const int imgid, const int sRGB, const int out_width,
1569 const int out_height, const int dng_mode)
1570 {
1571 *buf = NULL;
1572 try
1573 {
1574 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
1575 assert(image.get() != 0);
1576 read_metadata_threadsafe(image);
1577 Exiv2::ExifData &exifData = image->exifData();
1578
1579 // get rid of thumbnails
1580 Exiv2::ExifThumb(exifData).erase();
1581 Exiv2::ExifData::const_iterator pos;
1582
1583 {
1584 static const char *keys[] = {
1585 "Exif.Image.ImageWidth",
1586 "Exif.Image.ImageLength",
1587 "Exif.Image.BitsPerSample",
1588 "Exif.Image.Compression",
1589 "Exif.Image.PhotometricInterpretation",
1590 "Exif.Image.FillOrder",
1591 "Exif.Image.SamplesPerPixel",
1592 "Exif.Image.StripOffsets",
1593 "Exif.Image.RowsPerStrip",
1594 "Exif.Image.StripByteCounts",
1595 "Exif.Image.PlanarConfiguration",
1596 "Exif.Image.DNGVersion",
1597 "Exif.Image.DNGBackwardVersion"
1598 };
1599 static const guint n_keys = G_N_ELEMENTS(keys);
1600 dt_remove_exif_keys(exifData, keys, n_keys);
1601 }
1602
1603 /* Many tags should be removed in all cases as they are simply wrong also for dng files */
1604
1605 // remove subimage* trees, related to thumbnails or HDR usually; also UserCrop
1606 for(Exiv2::ExifData::iterator i = exifData.begin(); i != exifData.end();)
1607 {
1608 static const std::string needle = "Exif.SubImage";
1609 if(i->key().compare(0, needle.length(), needle) == 0)
1610 i = exifData.erase(i);
1611 else
1612 ++i;
1613 }
1614
1615 {
1616 static const char *keys[] = {
1617 // Canon color space info
1618 "Exif.Canon.ColorSpace",
1619 "Exif.Canon.ColorData",
1620
1621 // Nikon thumbnail data
1622 "Exif.Nikon3.Preview",
1623 "Exif.NikonPreview.JPEGInterchangeFormat",
1624
1625 // DNG stuff that is irrelevant or misleading
1626 "Exif.Image.DNGPrivateData",
1627 "Exif.Image.DefaultBlackRender",
1628 "Exif.Image.DefaultCropOrigin",
1629 "Exif.Image.DefaultCropSize",
1630 "Exif.Image.RawDataUniqueID",
1631 "Exif.Image.OriginalRawFileName",
1632 "Exif.Image.OriginalRawFileData",
1633 "Exif.Image.ActiveArea",
1634 "Exif.Image.MaskedAreas",
1635 "Exif.Image.AsShotICCProfile",
1636 "Exif.Image.OpcodeList1",
1637 "Exif.Image.OpcodeList2",
1638 "Exif.Image.OpcodeList3",
1639 "Exif.Photo.MakerNote",
1640
1641 // Pentax thumbnail data
1642 "Exif.Pentax.PreviewResolution",
1643 "Exif.Pentax.PreviewLength",
1644 "Exif.Pentax.PreviewOffset",
1645 "Exif.PentaxDng.PreviewResolution",
1646 "Exif.PentaxDng.PreviewLength",
1647 "Exif.PentaxDng.PreviewOffset",
1648 // Pentax color info
1649 "Exif.PentaxDng.ColorInfo",
1650
1651 // Minolta thumbnail data
1652 "Exif.Minolta.Thumbnail",
1653 "Exif.Minolta.ThumbnailOffset",
1654 "Exif.Minolta.ThumbnailLength",
1655
1656 // Sony thumbnail data
1657 "Exif.SonyMinolta.ThumbnailOffset",
1658 "Exif.SonyMinolta.ThumbnailLength",
1659
1660 // Olympus thumbnail data
1661 "Exif.Olympus.Thumbnail",
1662 "Exif.Olympus.ThumbnailOffset",
1663 "Exif.Olympus.ThumbnailLength"
1664
1665 "Exif.Image.BaselineExposureOffset",
1666 };
1667 static const guint n_keys = G_N_ELEMENTS(keys);
1668 dt_remove_exif_keys(exifData, keys, n_keys);
1669 }
1670 #if EXIV2_MINOR_VERSION >= 23
1671 {
1672 // Exiv2 versions older than 0.23 drop all EXIF if the code below is executed
1673 // Samsung makernote cleanup, the entries below have no relevance for exported images
1674 static const char *keys[] = {
1675 "Exif.Samsung2.SensorAreas",
1676 "Exif.Samsung2.ColorSpace",
1677 "Exif.Samsung2.EncryptionKey",
1678 "Exif.Samsung2.WB_RGGBLevelsUncorrected",
1679 "Exif.Samsung2.WB_RGGBLevelsAuto",
1680 "Exif.Samsung2.WB_RGGBLevelsIlluminator1",
1681 "Exif.Samsung2.WB_RGGBLevelsIlluminator2",
1682 "Exif.Samsung2.WB_RGGBLevelsBlack",
1683 "Exif.Samsung2.ColorMatrix",
1684 "Exif.Samsung2.ColorMatrixSRGB",
1685 "Exif.Samsung2.ColorMatrixAdobeRGB",
1686 "Exif.Samsung2.ToneCurve1",
1687 "Exif.Samsung2.ToneCurve2",
1688 "Exif.Samsung2.ToneCurve3",
1689 "Exif.Samsung2.ToneCurve4"
1690 };
1691 static const guint n_keys = G_N_ELEMENTS(keys);
1692 dt_remove_exif_keys(exifData, keys, n_keys);
1693 }
1694 #endif
1695
1696 static const char *dngkeys[] = {
1697 // Embedded color profile info
1698 "Exif.Image.CalibrationIlluminant1",
1699 "Exif.Image.CalibrationIlluminant2",
1700 "Exif.Image.ColorMatrix1",
1701 "Exif.Image.ColorMatrix2",
1702 "Exif.Image.ForwardMatrix1",
1703 "Exif.Image.ForwardMatrix2",
1704 "Exif.Image.ProfileCalibrationSignature",
1705 "Exif.Image.ProfileCopyright",
1706 "Exif.Image.ProfileEmbedPolicy",
1707 "Exif.Image.ProfileHueSatMapData1",
1708 "Exif.Image.ProfileHueSatMapData2",
1709 "Exif.Image.ProfileHueSatMapDims",
1710 "Exif.Image.ProfileHueSatMapEncoding",
1711 "Exif.Image.ProfileLookTableData",
1712 "Exif.Image.ProfileLookTableDims",
1713 "Exif.Image.ProfileLookTableEncoding",
1714 "Exif.Image.ProfileName",
1715 "Exif.Image.ProfileToneCurve",
1716 "Exif.Image.ReductionMatrix1",
1717 "Exif.Image.ReductionMatrix2"
1718 };
1719 static const guint n_dngkeys = G_N_ELEMENTS(dngkeys);
1720 dt_remove_exif_keys(exifData, dngkeys, n_dngkeys);
1721
1722 /* Write appropriate color space tag if using sRGB output */
1723 if(sRGB)
1724 exifData["Exif.Photo.ColorSpace"] = uint16_t(1); /* sRGB */
1725 else
1726 exifData["Exif.Photo.ColorSpace"] = uint16_t(0xFFFF); /* Uncalibrated */
1727
1728 // we don't write the orientation here for dng as it is set in dt_imageio_dng_write_tiff_header
1729 // or might be defined in this blob.
1730 if(!dng_mode) exifData["Exif.Image.Orientation"] = uint16_t(1);
1731
1732 /* Replace RAW dimension with output dimensions (for example after crop/scale, or orientation for dng
1733 * mode) */
1734 if(out_width > 0) exifData["Exif.Photo.PixelXDimension"] = (uint32_t)out_width;
1735 if(out_height > 0) exifData["Exif.Photo.PixelYDimension"] = (uint32_t)out_height;
1736
1737 const int resolution = dt_conf_get_int("metadata/resolution");
1738 exifData["Exif.Image.XResolution"] = Exiv2::Rational(resolution, 1);
1739 exifData["Exif.Image.YResolution"] = Exiv2::Rational(resolution, 1);
1740 exifData["Exif.Image.ResolutionUnit"] = uint16_t(2); /* inches */
1741
1742 exifData["Exif.Image.Software"] = darktable_package_string;
1743
1744 // TODO: find a nice place for the missing metadata (tags, publisher, colorlabels?). Additionally find out
1745 // how to embed XMP data.
1746 // And shall we add a description of the history stack to Exif.Image.ImageHistory?
1747 if(imgid >= 0)
1748 {
1749 /* Delete metadata taken from the original file if it's fields we manage in dt, too */
1750 static const char * keys[] = {
1751 "Exif.Image.Artist",
1752 "Exif.Image.ImageDescription",
1753 "Exif.Photo.UserComment",
1754 "Exif.Image.Copyright",
1755 "Exif.Image.Rating",
1756 "Exif.Image.RatingPercent",
1757 "Exif.GPSInfo.GPSVersionID",
1758 "Exif.GPSInfo.GPSLongitudeRef",
1759 "Exif.GPSInfo.GPSLatitudeRef",
1760 "Exif.GPSInfo.GPSLongitude",
1761 "Exif.GPSInfo.GPSLatitude",
1762 "Exif.GPSInfo.GPSAltitudeRef",
1763 "Exif.GPSInfo.GPSAltitude"
1764 };
1765 static const guint n_keys = G_N_ELEMENTS(keys);
1766 dt_remove_exif_keys(exifData, keys, n_keys);
1767
1768 GList *res = dt_metadata_get(imgid, "Xmp.dc.creator", NULL);
1769 if(res != NULL)
1770 {
1771 exifData["Exif.Image.Artist"] = (char *)res->data;
1772 g_list_free_full(res, &g_free);
1773 }
1774
1775 res = dt_metadata_get(imgid, "Xmp.dc.description", NULL);
1776 if(res != NULL)
1777 {
1778 char *desc = (char *)res->data;
1779 if(g_str_is_ascii(desc))
1780 exifData["Exif.Image.ImageDescription"] = desc;
1781 else
1782 exifData["Exif.Photo.UserComment"] = desc;
1783 g_list_free_full(res, &g_free);
1784 }
1785 #if EXIV2_TEST_VERSION(0,27,4)
1786 else
1787 // mandatory tag for TIFF/EP and recommended for Exif, empty is ok (unknown)
1788 // but correctly written only by exiv2 >= 0.27.4
1789 exifData["Exif.Image.ImageDescription"] = "";
1790 #endif
1791
1792 res = dt_metadata_get(imgid, "Xmp.dc.rights", NULL);
1793 if(res != NULL)
1794 {
1795 exifData["Exif.Image.Copyright"] = (char *)res->data;
1796 g_list_free_full(res, &g_free);
1797 }
1798 #if EXIV2_TEST_VERSION(0,27,4)
1799 else
1800 // mandatory tag for TIFF/EP and optional for Exif, empty is ok (unknown)
1801 // but correctly written only by exiv2 >= 0.27.4
1802 exifData["Exif.Image.Copyright"] = "";
1803 #endif
1804
1805 res = dt_metadata_get(imgid, "Xmp.xmp.Rating", NULL);
1806 if(res != NULL)
1807 {
1808 const int rating = GPOINTER_TO_INT(res->data) + 1;
1809 exifData["Exif.Image.Rating"] = rating;
1810 exifData["Exif.Image.RatingPercent"] = int(rating / 5. * 100.);
1811 g_list_free(res);
1812 }
1813
1814 // GPS data
1815 dt_remove_exif_geotag(exifData);
1816 const dt_image_t *cimg = dt_image_cache_get(darktable.image_cache, imgid, 'r');
1817 if(!std::isnan(cimg->geoloc.longitude) && !std::isnan(cimg->geoloc.latitude))
1818 {
1819 exifData["Exif.GPSInfo.GPSVersionID"] = "02 02 00 00";
1820 exifData["Exif.GPSInfo.GPSLongitudeRef"] = (cimg->geoloc.longitude < 0) ? "W" : "E";
1821 exifData["Exif.GPSInfo.GPSLatitudeRef"] = (cimg->geoloc.latitude < 0) ? "S" : "N";
1822
1823 long long_deg = (int)floor(fabs(cimg->geoloc.longitude));
1824 long lat_deg = (int)floor(fabs(cimg->geoloc.latitude));
1825 long long_min = (int)floor((fabs(cimg->geoloc.longitude) - floor(fabs(cimg->geoloc.longitude))) * 60000000);
1826 long lat_min = (int)floor((fabs(cimg->geoloc.latitude) - floor(fabs(cimg->geoloc.latitude))) * 60000000);
1827 gchar *long_str = g_strdup_printf("%ld/1 %ld/1000000 0/1", long_deg, long_min);
1828 gchar *lat_str = g_strdup_printf("%ld/1 %ld/1000000 0/1", lat_deg, lat_min);
1829 exifData["Exif.GPSInfo.GPSLongitude"] = long_str;
1830 exifData["Exif.GPSInfo.GPSLatitude"] = lat_str;
1831 g_free(long_str);
1832 g_free(lat_str);
1833 }
1834 if(!std::isnan(cimg->geoloc.elevation))
1835 {
1836 exifData["Exif.GPSInfo.GPSVersionID"] = "02 02 00 00";
1837 exifData["Exif.GPSInfo.GPSAltitudeRef"] = (cimg->geoloc.elevation < 0) ? "1" : "0";
1838
1839 long ele_dm = (int)floor(fabs(10.0 * cimg->geoloc.elevation));
1840 gchar *ele_str = g_strdup_printf("%ld/10", ele_dm);
1841 exifData["Exif.GPSInfo.GPSAltitude"] = ele_str;
1842 g_free(ele_str);
1843 }
1844
1845 // According to the Exif specs DateTime is to be set to the last modification time while
1846 // DateTimeOriginal is to be kept.
1847 // For us "keeping" it means to write out what we have in DB to support people adding a time offset in
1848 // the geotagging module.
1849 gchar new_datetime[DT_DATETIME_LENGTH];
1850 dt_gettime(new_datetime, sizeof(new_datetime));
1851 exifData["Exif.Image.DateTime"] = new_datetime;
1852 exifData["Exif.Image.DateTimeOriginal"] = cimg->exif_datetime_taken;
1853 exifData["Exif.Photo.DateTimeOriginal"] = cimg->exif_datetime_taken;
1854
1855 dt_image_cache_read_release(darktable.image_cache, cimg);
1856 }
1857
1858 Exiv2::Blob blob;
1859 Exiv2::ExifParser::encode(blob, Exiv2::bigEndian, exifData);
1860 const int length = blob.size();
1861 *buf = (uint8_t *)malloc(length+6);
1862 if (!*buf)
1863 {
1864 return 0;
1865 }
1866 memcpy(*buf, "Exif\000\000", 6);
1867 memcpy(*buf + 6, &(blob[0]), length);
1868 return length + 6;
1869 }
1870 catch(Exiv2::AnyError &e)
1871 {
1872 // std::cerr.rdbuf(savecerr);
1873 std::string s(e.what());
1874 std::cerr << "[exiv2 dt_exif_read_blob] " << path << ": " << s << std::endl;
1875 free(*buf);
1876 *buf = NULL;
1877 return 0;
1878 }
1879 }
1880
1881 // encode binary blob into text:
dt_exif_xmp_encode(const unsigned char * input,const int len,int * output_len)1882 char *dt_exif_xmp_encode(const unsigned char *input, const int len, int *output_len)
1883 {
1884 #define COMPRESS_THRESHOLD 100
1885
1886 gboolean do_compress = FALSE;
1887
1888 // if input data field exceeds a certain size we compress it and convert to base64;
1889 // main reason for compression: make more xmp data fit into 64k segment within
1890 // JPEG output files.
1891 char *config = dt_conf_get_string("compress_xmp_tags");
1892 if(config)
1893 {
1894 if(!strcmp(config, "always"))
1895 do_compress = TRUE;
1896 else if((len > COMPRESS_THRESHOLD) && !strcmp(config, "only large entries"))
1897 do_compress = TRUE;
1898 else
1899 do_compress = FALSE;
1900 g_free(config);
1901 }
1902
1903 return dt_exif_xmp_encode_internal(input, len, output_len, do_compress);
1904
1905 #undef COMPRESS_THRESHOLD
1906 }
1907
dt_exif_xmp_encode_internal(const unsigned char * input,const int len,int * output_len,gboolean do_compress)1908 char *dt_exif_xmp_encode_internal(const unsigned char *input, const int len, int *output_len, gboolean do_compress)
1909 {
1910 char *output = NULL;
1911
1912 if(do_compress)
1913 {
1914 int result;
1915 uLongf destLen = compressBound(len);
1916 unsigned char *buffer1 = (unsigned char *)malloc(destLen);
1917
1918 result = compress(buffer1, &destLen, input, len);
1919
1920 if(result != Z_OK)
1921 {
1922 free(buffer1);
1923 return NULL;
1924 }
1925
1926 // we store the compression factor
1927 const int factor = MIN(len / destLen + 1, 99);
1928
1929 char *buffer2 = (char *)g_base64_encode(buffer1, destLen);
1930 free(buffer1);
1931 if(!buffer2) return NULL;
1932
1933 int outlen = strlen(buffer2) + 5; // leading "gz" + compression factor + base64 string + trailing '\0'
1934 output = (char *)malloc(outlen);
1935 if(!output)
1936 {
1937 g_free(buffer2);
1938 return NULL;
1939 }
1940
1941 output[0] = 'g';
1942 output[1] = 'z';
1943 output[2] = factor / 10 + '0';
1944 output[3] = factor % 10 + '0';
1945 g_strlcpy(output + 4, buffer2, outlen);
1946 g_free(buffer2);
1947
1948 if(output_len) *output_len = outlen;
1949 }
1950 else
1951 {
1952 const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1953
1954 output = (char *)malloc(2 * len + 1);
1955 if(!output) return NULL;
1956
1957 if(output_len) *output_len = 2 * len + 1;
1958
1959 for(int i = 0; i < len; i++)
1960 {
1961 const int hi = input[i] >> 4;
1962 const int lo = input[i] & 15;
1963 output[2 * i] = hex[hi];
1964 output[2 * i + 1] = hex[lo];
1965 }
1966 output[2 * len] = '\0';
1967 }
1968
1969 return output;
1970 }
1971
1972 // and back to binary
dt_exif_xmp_decode(const char * input,const int len,int * output_len)1973 unsigned char *dt_exif_xmp_decode(const char *input, const int len, int *output_len)
1974 {
1975 unsigned char *output = NULL;
1976
1977 // check if data is in compressed format
1978 if(!strncmp(input, "gz", 2))
1979 {
1980 // we have compressed data in base64 representation with leading "gz"
1981
1982 // get stored compression factor so we know the needed buffer size for uncompress
1983 const float factor = 10 * (input[2] - '0') + (input[3] - '0');
1984
1985 // get a rw copy of input buffer omitting leading "gz" and compression factor
1986 unsigned char *buffer = (unsigned char *)strdup(input + 4);
1987 if(!buffer) return NULL;
1988
1989 // decode from base64 to compressed binary
1990 gsize compressed_size;
1991 g_base64_decode_inplace((char *)buffer, &compressed_size);
1992
1993 // do the actual uncompress step
1994 int result = Z_BUF_ERROR;
1995 uLongf bufLen = factor * compressed_size;
1996 uLongf destLen;
1997
1998 // we know the actual compression factor but if that fails we re-try with
1999 // increasing buffer sizes, eg. we don't know (unlikely) factors > 99
2000 do
2001 {
2002 if(output) free(output);
2003 output = (unsigned char *)malloc(bufLen);
2004 if(!output) break;
2005
2006 destLen = bufLen;
2007
2008 result = uncompress(output, &destLen, buffer, compressed_size);
2009
2010 bufLen *= 2;
2011
2012 } while(result == Z_BUF_ERROR);
2013
2014
2015 free(buffer);
2016
2017 if(result != Z_OK)
2018 {
2019 if(output) free(output);
2020 return NULL;
2021 }
2022
2023 if(output_len) *output_len = destLen;
2024 }
2025 else
2026 {
2027 // we have uncompressed data in hexadecimal ascii representation
2028
2029 // ascii table:
2030 // 48- 57 0-9
2031 // 97-102 a-f
2032 #define TO_BINARY(a) (a > 57 ? a - 97 + 10 : a - 48)
2033
2034 // make sure that we don't find any unexpected characters indicating corrupted data
2035 if(strspn(input, "0123456789abcdef") != strlen(input)) return NULL;
2036
2037 output = (unsigned char *)malloc(len / 2);
2038 if(!output) return NULL;
2039
2040 if(output_len) *output_len = len / 2;
2041
2042 for(int i = 0; i < len / 2; i++)
2043 {
2044 const int hi = TO_BINARY(input[2 * i]);
2045 const int lo = TO_BINARY(input[2 * i + 1]);
2046 output[i] = (hi << 4) | lo;
2047 }
2048 #undef TO_BINARY
2049 }
2050
2051 return output;
2052 }
2053
_exif_import_tags(dt_image_t * img,Exiv2::XmpData::iterator & pos)2054 static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos)
2055 {
2056 // tags in array
2057 const int cnt = pos->count();
2058
2059 sqlite3_stmt *stmt_sel_id, *stmt_ins_tags, *stmt_ins_tagged;
2060 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT id FROM data.tags WHERE name = ?1", -1,
2061 &stmt_sel_id, NULL);
2062 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "INSERT INTO data.tags (id, name) VALUES (NULL, ?1)",
2063 -1, &stmt_ins_tags, NULL);
2064 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
2065 "INSERT INTO main.tagged_images (tagid, imgid, position)"
2066 " VALUES (?1, ?2,"
2067 " (SELECT (IFNULL(MAX(position),0) & 0xFFFFFFFF00000000) + (1 << 32)"
2068 " FROM main.tagged_images))",
2069 -1, &stmt_ins_tagged, NULL);
2070 for(int i = 0; i < cnt; i++)
2071 {
2072 char tagbuf[1024];
2073 std::string pos_str = pos->toString(i);
2074 g_strlcpy(tagbuf, pos_str.c_str(), sizeof(tagbuf));
2075 int tagid = -1;
2076 char *tag = tagbuf;
2077 while(tag)
2078 {
2079 char *next_tag = strstr(tag, ",");
2080 if(next_tag) *(next_tag++) = 0;
2081 // check if tag is available, get its id:
2082 for(int k = 0; k < 2; k++)
2083 {
2084 DT_DEBUG_SQLITE3_BIND_TEXT(stmt_sel_id, 1, tag, -1, SQLITE_TRANSIENT);
2085 if(sqlite3_step(stmt_sel_id) == SQLITE_ROW) tagid = sqlite3_column_int(stmt_sel_id, 0);
2086 sqlite3_reset(stmt_sel_id);
2087 sqlite3_clear_bindings(stmt_sel_id);
2088
2089 if(tagid > 0) break;
2090
2091 fprintf(stderr, "[xmp_import] creating tag: %s\n", tag);
2092 // create this tag (increment id, leave icon empty), retry.
2093 DT_DEBUG_SQLITE3_BIND_TEXT(stmt_ins_tags, 1, tag, -1, SQLITE_TRANSIENT);
2094 sqlite3_step(stmt_ins_tags);
2095 sqlite3_reset(stmt_ins_tags);
2096 sqlite3_clear_bindings(stmt_ins_tags);
2097 }
2098 // associate image and tag.
2099 DT_DEBUG_SQLITE3_BIND_INT(stmt_ins_tagged, 1, tagid);
2100 DT_DEBUG_SQLITE3_BIND_INT(stmt_ins_tagged, 2, img->id);
2101 sqlite3_step(stmt_ins_tagged);
2102 sqlite3_reset(stmt_ins_tagged);
2103 sqlite3_clear_bindings(stmt_ins_tagged);
2104
2105 tag = next_tag;
2106 }
2107 }
2108 sqlite3_finalize(stmt_sel_id);
2109 sqlite3_finalize(stmt_ins_tags);
2110 sqlite3_finalize(stmt_ins_tagged);
2111 }
2112
2113 typedef struct history_entry_t
2114 {
2115 char *operation;
2116 gboolean enabled;
2117 int modversion;
2118 unsigned char *params;
2119 int params_len;
2120 char *multi_name;
2121 int multi_priority;
2122 int blendop_version;
2123 unsigned char *blendop_params;
2124 int blendop_params_len;
2125 int num;
2126 double iop_order; // kept for compatibility with xmp version < 4
2127
2128 // sanity checking
2129 gboolean have_operation, have_params, have_modversion;
2130 } history_entry_t;
2131
2132 // used for a hash table that maps mask_id to the mask data
2133 typedef struct mask_entry_t
2134 {
2135 int mask_id;
2136 int mask_type;
2137 char *mask_name;
2138 int mask_version;
2139 unsigned char *mask_points;
2140 int mask_points_len;
2141 int mask_nb;
2142 unsigned char *mask_src;
2143 int mask_src_len;
2144 gboolean already_added;
2145 int mask_num;
2146 int version;
2147 } mask_entry_t;
2148
2149 static void print_history_entry(history_entry_t *entry) __attribute__((unused));
print_history_entry(history_entry_t * entry)2150 static void print_history_entry(history_entry_t *entry)
2151 {
2152 if(!entry || !entry->operation)
2153 {
2154 std::cout << "malformed entry" << std::endl;
2155 return;
2156 }
2157
2158 std::cout << entry->operation << std::endl;
2159 std::cout << " modversion :" << entry->modversion << std::endl;
2160 std::cout << " enabled :" << entry->enabled << std::endl;
2161 std::cout << " params :" << (entry->params ? "<found>" : "<missing>") << std::endl;
2162 std::cout << " multi_name :" << (entry->multi_name ? entry->multi_name : "<missing>") << std::endl;
2163 std::cout << " multi_priority :" << entry->multi_priority << std::endl;
2164 std::cout << " iop_order :" << entry->iop_order << std::endl;
2165 std::cout << " blendop_version :" << entry->blendop_version << std::endl;
2166 std::cout << " blendop_params :" << (entry->blendop_params ? "<found>" : "<missing>") << std::endl;
2167 std::cout << std::endl;
2168 }
2169
free_history_entry(gpointer data)2170 static void free_history_entry(gpointer data)
2171 {
2172 history_entry_t *entry = (history_entry_t *)data;
2173 g_free(entry->operation);
2174 g_free(entry->multi_name);
2175 free(entry->params);
2176 free(entry->blendop_params);
2177 free(entry);
2178 }
2179
2180 // we have to use pugixml as the old format could contain empty rdf:li elements in the multi_name array
2181 // which causes problems when accessing it with libexiv2 :(
2182 // superold is a flag indicating that data is wrapped in <rdf:Bag> instead of <rdf:Seq>.
read_history_v1(const std::string & xmpPacket,const char * filename,const int superold)2183 static GList *read_history_v1(const std::string &xmpPacket, const char *filename, const int superold)
2184 {
2185 GList *history_entries = NULL;
2186
2187 pugi::xml_document doc;
2188 #if defined(PUGIXML_VERSION) && PUGIXML_VERSION >= 150
2189 pugi::xml_parse_result result = doc.load_string(xmpPacket.c_str());
2190 #else
2191 pugi::xml_parse_result result = doc.load(xmpPacket.c_str());
2192 #endif
2193
2194 if(!result)
2195 {
2196 std::cerr << "XML '" << filename << "' parsed with errors" << std::endl;
2197 std::cerr << "Error description: " << result.description() << std::endl;
2198 std::cerr << "Error offset: " << result.offset << std::endl;
2199 return NULL;
2200 }
2201
2202 // get the old elements
2203 // select_single_node() is deprecated and just kept for old versions shipped in some distributions
2204 #if defined(PUGIXML_VERSION) && PUGIXML_VERSION >= 150
2205 pugi::xpath_node modversion = superold ?
2206 doc.select_node("//darktable:history_modversion/rdf:Bag"):
2207 doc.select_node("//darktable:history_modversion/rdf:Seq");
2208 pugi::xpath_node enabled = superold ?
2209 doc.select_node("//darktable:history_enabled/rdf:Bag"):
2210 doc.select_node("//darktable:history_enabled/rdf:Seq");
2211 pugi::xpath_node operation = superold ?
2212 doc.select_node("//darktable:history_operation/rdf:Bag"):
2213 doc.select_node("//darktable:history_operation/rdf:Seq");
2214 pugi::xpath_node params = superold ?
2215 doc.select_node("//darktable:history_params/rdf:Bag"):
2216 doc.select_node("//darktable:history_params/rdf:Seq");
2217 pugi::xpath_node blendop_params = superold ?
2218 doc.select_node("//darktable:blendop_params/rdf:Bag"):
2219 doc.select_node("//darktable:blendop_params/rdf:Seq");
2220 pugi::xpath_node blendop_version = superold ?
2221 doc.select_node("//darktable:blendop_version/rdf:Bag"):
2222 doc.select_node("//darktable:blendop_version/rdf:Seq");
2223 pugi::xpath_node multi_priority = superold ?
2224 doc.select_node("//darktable:multi_priority/rdf:Bag"):
2225 doc.select_node("//darktable:multi_priority/rdf:Seq");
2226 pugi::xpath_node multi_name = superold ?
2227 doc.select_node("//darktable:multi_name/rdf:Bag"):
2228 doc.select_node("//darktable:multi_name/rdf:Seq");
2229 #else
2230 pugi::xpath_node modversion = superold ?
2231 doc.select_single_node("//darktable:history_modversion/rdf:Bag"):
2232 doc.select_single_node("//darktable:history_modversion/rdf:Seq");
2233 pugi::xpath_node enabled = superold ?
2234 doc.select_single_node("//darktable:history_enabled/rdf:Bag"):
2235 doc.select_single_node("//darktable:history_enabled/rdf:Seq");
2236 pugi::xpath_node operation = superold ?
2237 doc.select_single_node("//darktable:history_operation/rdf:Bag"):
2238 doc.select_single_node("//darktable:history_operation/rdf:Seq");
2239 pugi::xpath_node params = superold ?
2240 doc.select_single_node("//darktable:history_params/rdf:Bag"):
2241 doc.select_single_node("//darktable:history_params/rdf:Seq");
2242 pugi::xpath_node blendop_params = superold ?
2243 doc.select_single_node("//darktable:blendop_params/rdf:Bag"):
2244 doc.select_single_node("//darktable:blendop_params/rdf:Seq");
2245 pugi::xpath_node blendop_version = superold ?
2246 doc.select_single_node("//darktable:blendop_version/rdf:Bag"):
2247 doc.select_single_node("//darktable:blendop_version/rdf:Seq");
2248 pugi::xpath_node multi_priority = superold ?
2249 doc.select_single_node("//darktable:multi_priority/rdf:Bag"):
2250 doc.select_single_node("//darktable:multi_priority/rdf:Seq");
2251 pugi::xpath_node multi_name = superold ?
2252 doc.select_single_node("//darktable:multi_name/rdf:Bag"):
2253 doc.select_single_node("//darktable:multi_name/rdf:Seq");
2254 #endif
2255
2256 // fill the list of history entries. we are iterating over history_operation as we know that it's there.
2257 // the other iters are taken care of manually.
2258 auto modversion_iter = modversion.node().children().begin();
2259 auto enabled_iter = enabled.node().children().begin();
2260 auto params_iter = params.node().children().begin();
2261 auto blendop_params_iter = blendop_params.node().children().begin();
2262 auto blendop_version_iter = blendop_version.node().children().begin();
2263 auto multi_priority_iter = multi_priority.node().children().begin();
2264 auto multi_name_iter = multi_name.node().children().begin();
2265
2266 for(pugi::xml_node operation_iter: operation.node().children())
2267 {
2268 history_entry_t *current_entry = (history_entry_t *)calloc(1, sizeof(history_entry_t));
2269 current_entry->blendop_version = 1; // default version in case it's not specified
2270 history_entries = g_list_append(history_entries, current_entry);
2271
2272 current_entry->operation = g_strdup(operation_iter.child_value());
2273
2274 current_entry->enabled = g_strcmp0(enabled_iter->child_value(), "0") != 0;
2275
2276 current_entry->modversion = atoi(modversion_iter->child_value());
2277
2278 current_entry->params = dt_exif_xmp_decode(params_iter->child_value(), strlen(params_iter->child_value()),
2279 ¤t_entry->params_len);
2280
2281 if(multi_name && multi_name_iter != multi_name.node().children().end())
2282 {
2283 current_entry->multi_name = g_strdup(multi_name_iter->child_value());
2284 multi_name_iter++;
2285 }
2286
2287 if(multi_priority && multi_priority_iter != multi_priority.node().children().end())
2288 {
2289 current_entry->multi_priority = atoi(multi_priority_iter->child_value());
2290 multi_priority_iter++;
2291 }
2292
2293 if(blendop_version && blendop_version_iter != blendop_version.node().children().end())
2294 {
2295 current_entry->blendop_version = atoi(blendop_version_iter->child_value());
2296 blendop_version_iter++;
2297 }
2298
2299 if(blendop_params && blendop_params_iter != blendop_params.node().children().end())
2300 {
2301 current_entry->blendop_params = dt_exif_xmp_decode(blendop_params_iter->child_value(),
2302 strlen(blendop_params_iter->child_value()),
2303 ¤t_entry->blendop_params_len);
2304 blendop_params_iter++;
2305 }
2306
2307 current_entry->iop_order = -1.0;
2308
2309 modversion_iter++;
2310 enabled_iter++;
2311 params_iter++;
2312 }
2313
2314 return history_entries;
2315 }
2316
read_history_v2(Exiv2::XmpData & xmpData,const char * filename)2317 static GList *read_history_v2(Exiv2::XmpData &xmpData, const char *filename)
2318 {
2319 GList *history_entries = NULL;
2320 history_entry_t *current_entry = NULL;
2321
2322 for(auto history = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.history")); history != xmpData.end(); history++)
2323 {
2324 // TODO: support human readable params via introspection with something like this:
2325 // XmpText: Xmp.darktable.history[1]/darktable:settings[1]/darktable:name = width
2326 // XmpText: Xmp.darktable.history[1]/darktable:settings[1]/darktable:value = 23
2327
2328 char *key = g_strdup(history->key().c_str());
2329 char *key_iter = key;
2330 if(g_str_has_prefix(key, "Xmp.darktable.history["))
2331 {
2332 key_iter += strlen("Xmp.darktable.history[");
2333 errno = 0;
2334 unsigned int n = strtol(key_iter, &key_iter, 10);
2335 if(errno)
2336 {
2337 std::cerr << "error reading history from '" << key << "' (" << filename << ")" << std::endl;
2338 g_list_free_full(history_entries, free_history_entry);
2339 g_free(key);
2340 return NULL;
2341 }
2342
2343 // skip everything that isn't part of the actual array
2344 if(*(key_iter++) != ']')
2345 {
2346 std::cerr << "error reading history from '" << key << "' (" << filename << ")" << std::endl;
2347 g_list_free_full(history_entries, free_history_entry);
2348 g_free(key);
2349 return NULL;
2350 }
2351 if(*(key_iter++) != '/') goto skip;
2352 if(*key_iter == '?') key_iter++;
2353
2354 // make sure we are filling in the details of the correct entry
2355 unsigned int length = g_list_length(history_entries);
2356 if(n > length)
2357 {
2358 current_entry = (history_entry_t *)calloc(1, sizeof(history_entry_t));
2359 current_entry->blendop_version = 1; // default version in case it's not specified
2360 current_entry->iop_order = -1.0;
2361 history_entries = g_list_append(history_entries, current_entry);
2362 }
2363 else if(n < length)
2364 {
2365 // AFAICT this can't happen with regular exiv2 parsed XMP data, but better safe than sorry.
2366 // it can happen though when constructing things in a unusual order and then passing it to us without
2367 // serializing it in between
2368 current_entry = (history_entry_t *)g_list_nth_data(history_entries, n - 1); // XMP starts counting at 1!
2369 }
2370
2371 // go on reading things into current_entry
2372 if(g_str_has_prefix(key_iter, "darktable:operation"))
2373 {
2374 current_entry->have_operation = TRUE;
2375 current_entry->operation = g_strdup(history->value().toString().c_str());
2376 }
2377 else if(g_str_has_prefix(key_iter, "darktable:num"))
2378 {
2379 current_entry->num = history->value().toLong();
2380 }
2381 else if(g_str_has_prefix(key_iter, "darktable:enabled"))
2382 {
2383 current_entry->enabled = history->value().toLong() == 1;
2384 }
2385 else if(g_str_has_prefix(key_iter, "darktable:modversion"))
2386 {
2387 current_entry->have_modversion = TRUE;
2388 current_entry->modversion = history->value().toLong();
2389 }
2390 else if(g_str_has_prefix(key_iter, "darktable:params"))
2391 {
2392 current_entry->have_params = TRUE;
2393 current_entry->params = dt_exif_xmp_decode(history->value().toString().c_str(), history->value().size(),
2394 ¤t_entry->params_len);
2395 }
2396 else if(g_str_has_prefix(key_iter, "darktable:multi_name"))
2397 {
2398 current_entry->multi_name = g_strdup(history->value().toString().c_str());
2399 }
2400 else if(g_str_has_prefix(key_iter, "darktable:multi_priority"))
2401 {
2402 current_entry->multi_priority = history->value().toLong();
2403 }
2404 else if(g_str_has_prefix(key_iter, "darktable:iop_order"))
2405 {
2406 // we ensure reading the iop_order as a high precision float
2407 string str = g_strdup(history->value().toString().c_str());
2408 static const std::locale& c_locale = std::locale("C");
2409 std::istringstream istring(str);
2410 istring.imbue(c_locale);
2411 istring >> current_entry->iop_order;
2412 }
2413 else if(g_str_has_prefix(key_iter, "darktable:blendop_version"))
2414 {
2415 current_entry->blendop_version = history->value().toLong();
2416 }
2417 else if(g_str_has_prefix(key_iter, "darktable:blendop_params"))
2418 {
2419 current_entry->blendop_params = dt_exif_xmp_decode(history->value().toString().c_str(),
2420 history->value().size(),
2421 ¤t_entry->blendop_params_len);
2422 }
2423 }
2424 skip:
2425 g_free(key);
2426 }
2427
2428 // a final sanity check
2429 for(GList *iter = history_entries; iter; iter = g_list_next(iter))
2430 {
2431 history_entry_t *entry = (history_entry_t *)iter->data;
2432 if(!(entry->have_operation && entry->have_params && entry->have_modversion))
2433 {
2434 std::cerr << "[exif] error: reading history from '" << filename << "' failed due to missing tags" << std::endl;
2435 g_list_free_full(history_entries, free_history_entry);
2436 history_entries = NULL;
2437 break;
2438 }
2439 }
2440
2441 return history_entries;
2442 }
2443
free_mask_entry(gpointer data)2444 void free_mask_entry(gpointer data)
2445 {
2446 mask_entry_t *entry = (mask_entry_t *)data;
2447 g_free(entry->mask_name);
2448 free(entry->mask_points);
2449 free(entry->mask_src);
2450 free(entry);
2451 }
2452
read_masks(Exiv2::XmpData & xmpData,const char * filename,const int version)2453 static GHashTable *read_masks(Exiv2::XmpData &xmpData, const char *filename, const int version)
2454 {
2455 GHashTable *mask_entries = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_mask_entry);
2456
2457 // TODO: turn that into something like Xmp.darktable.history!
2458 Exiv2::XmpData::iterator mask;
2459 Exiv2::XmpData::iterator mask_name;
2460 Exiv2::XmpData::iterator mask_type;
2461 Exiv2::XmpData::iterator mask_version;
2462 Exiv2::XmpData::iterator mask_id;
2463 Exiv2::XmpData::iterator mask_nb;
2464 Exiv2::XmpData::iterator mask_src;
2465 if((mask = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask"))) != xmpData.end()
2466 && (mask_src = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_src"))) != xmpData.end()
2467 && (mask_name = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_name"))) != xmpData.end()
2468 && (mask_type = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_type"))) != xmpData.end()
2469 && (mask_version = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_version"))) != xmpData.end()
2470 && (mask_id = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_id"))) != xmpData.end()
2471 && (mask_nb = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.mask_nb"))) != xmpData.end())
2472 {
2473 // fixes API change happened after exiv2 v0.27.2.1
2474 const size_t cnt = (size_t)mask->count();
2475 const size_t mask_src_cnt = (size_t)mask_src->count();
2476 const size_t mask_name_cnt = (size_t)mask_name->count();
2477 const size_t mask_type_cnt = (size_t)mask_type->count();
2478 const size_t mask_version_cnt = (size_t)mask_version->count();
2479 const size_t mask_id_cnt = (size_t)mask_id->count();
2480 const size_t mask_nb_cnt = (size_t)mask_nb->count();
2481 if(cnt == mask_src_cnt && cnt == mask_name_cnt && cnt == mask_type_cnt
2482 && cnt == mask_version_cnt && cnt == mask_id_cnt && cnt == mask_nb_cnt)
2483 {
2484 for(size_t i = 0; i < cnt; i++)
2485 {
2486 mask_entry_t *entry = (mask_entry_t *)calloc(1, sizeof(mask_entry_t));
2487
2488 entry->version = version;
2489 entry->mask_id = mask_id->toLong(i);
2490 entry->mask_type = mask_type->toLong(i);
2491 std::string mask_name_str = mask_name->toString(i);
2492 if(mask_name_str.c_str() != NULL)
2493 entry->mask_name = g_strdup(mask_name_str.c_str());
2494 else
2495 entry->mask_name = g_strdup("form");
2496
2497 entry->mask_version = mask_version->toLong(i);
2498
2499 std::string mask_str = mask->toString(i);
2500 const char *mask_c = mask_str.c_str();
2501 const size_t mask_c_len = strlen(mask_c);
2502 entry->mask_points = dt_exif_xmp_decode(mask_c, mask_c_len, &entry->mask_points_len);
2503
2504 entry->mask_nb = mask_nb->toLong(i);
2505
2506 std::string mask_src_str = mask_src->toString(i);
2507 const char *mask_src_c = mask_src_str.c_str();
2508 const size_t mask_src_c_len = strlen(mask_src_c);
2509 entry->mask_src = dt_exif_xmp_decode(mask_src_c, mask_src_c_len, &entry->mask_src_len);
2510
2511 g_hash_table_insert(mask_entries, &entry->mask_id, (gpointer)entry);
2512 }
2513 }
2514 }
2515
2516 return mask_entries;
2517 }
2518
read_masks_v3(Exiv2::XmpData & xmpData,const char * filename,const int version)2519 static GList *read_masks_v3(Exiv2::XmpData &xmpData, const char *filename, const int version)
2520 {
2521 GList *history_entries = NULL;
2522 mask_entry_t *current_entry = NULL;
2523
2524 for(auto history = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.masks_history")); history != xmpData.end(); history++)
2525 {
2526 // TODO: support human readable params via introspection with something like this:
2527 // XmpText: Xmp.darktable.history[1]/darktable:settings[1]/darktable:name = width
2528 // XmpText: Xmp.darktable.history[1]/darktable:settings[1]/darktable:value = 23
2529
2530 char *key = g_strdup(history->key().c_str());
2531 char *key_iter = key;
2532 if(g_str_has_prefix(key, "Xmp.darktable.masks_history["))
2533 {
2534 key_iter += strlen("Xmp.darktable.masks_history[");
2535 errno = 0;
2536 unsigned int n = strtol(key_iter, &key_iter, 10);
2537 if(errno)
2538 {
2539 std::cerr << "error reading masks history from '" << key << "' (" << filename << ")" << std::endl;
2540 g_list_free_full(history_entries, free_mask_entry);
2541 g_free(key);
2542 return NULL;
2543 }
2544
2545 // skip everything that isn't part of the actual array
2546 if(*(key_iter++) != ']')
2547 {
2548 std::cerr << "error reading masks history from '" << key << "' (" << filename << ")" << std::endl;
2549 g_list_free_full(history_entries, free_mask_entry);
2550 g_free(key);
2551 return NULL;
2552 }
2553 if(*(key_iter++) != '/') goto skip;
2554 if(*key_iter == '?') key_iter++;
2555
2556 // make sure we are filling in the details of the correct entry
2557 unsigned int length = g_list_length(history_entries);
2558 if(n > length)
2559 {
2560 current_entry = (mask_entry_t *)calloc(1, sizeof(mask_entry_t));
2561 current_entry->version = version;
2562 history_entries = g_list_append(history_entries, current_entry);
2563 }
2564 else if(n < length)
2565 {
2566 // AFAICT this can't happen with regular exiv2 parsed XMP data, but better safe than sorry.
2567 // it can happen though when constructing things in a unusual order and then passing it to us without
2568 // serializing it in between
2569 current_entry = (mask_entry_t *)g_list_nth_data(history_entries, n - 1); // XMP starts counting at 1!
2570 }
2571
2572 // go on reading things into current_entry
2573 if(g_str_has_prefix(key_iter, "darktable:mask_num"))
2574 {
2575 current_entry->mask_num = history->value().toLong();
2576 }
2577 else if(g_str_has_prefix(key_iter, "darktable:mask_id"))
2578 {
2579 current_entry->mask_id = history->value().toLong();
2580 }
2581 else if(g_str_has_prefix(key_iter, "darktable:mask_type"))
2582 {
2583 current_entry->mask_type = history->value().toLong();
2584 }
2585 else if(g_str_has_prefix(key_iter, "darktable:mask_name"))
2586 {
2587 current_entry->mask_name = g_strdup(history->value().toString().c_str());
2588 }
2589 else if(g_str_has_prefix(key_iter, "darktable:mask_version"))
2590 {
2591 current_entry->mask_version = history->value().toLong();
2592 }
2593 else if(g_str_has_prefix(key_iter, "darktable:mask_points"))
2594 {
2595 current_entry->mask_points = dt_exif_xmp_decode(history->value().toString().c_str(), history->value().size(), ¤t_entry->mask_points_len);
2596 }
2597 else if(g_str_has_prefix(key_iter, "darktable:mask_nb"))
2598 {
2599 current_entry->mask_nb = history->value().toLong();
2600 }
2601 else if(g_str_has_prefix(key_iter, "darktable:mask_src"))
2602 {
2603 current_entry->mask_src = dt_exif_xmp_decode(history->value().toString().c_str(), history->value().size(), ¤t_entry->mask_src_len);
2604 }
2605
2606 }
2607 skip:
2608 g_free(key);
2609 }
2610
2611 return history_entries;
2612 }
2613
add_mask_entry_to_db(int imgid,mask_entry_t * entry)2614 static void add_mask_entry_to_db(int imgid, mask_entry_t *entry)
2615 {
2616 // add the mask entry only once
2617 if(entry->already_added)
2618 return;
2619 entry->already_added = TRUE;
2620
2621 const int mask_num = 0;
2622
2623 sqlite3_stmt *stmt;
2624 DT_DEBUG_SQLITE3_PREPARE_V2(
2625 dt_database_get(darktable.db),
2626 "INSERT INTO main.masks_history (imgid, num, formid, form, name, version, points, points_count, source) "
2627 "VALUES (?1, ?9, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
2628 -1, &stmt, NULL);
2629 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
2630 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, entry->mask_id);
2631 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, entry->mask_type);
2632 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, entry->mask_name, -1, SQLITE_TRANSIENT);
2633 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, entry->mask_version);
2634 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 6, entry->mask_points, entry->mask_points_len, SQLITE_TRANSIENT);
2635 DT_DEBUG_SQLITE3_BIND_INT(stmt, 7, entry->mask_nb);
2636 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 8, entry->mask_src, entry->mask_src_len, SQLITE_TRANSIENT);
2637 if(entry->version < 3)
2638 {
2639 DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, mask_num);
2640 }
2641 else
2642 {
2643 DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, entry->mask_num);
2644 }
2645 sqlite3_step(stmt);
2646 sqlite3_finalize(stmt);
2647 }
2648
add_non_clone_mask_entries_to_db(gpointer key,gpointer value,gpointer user_data)2649 static void add_non_clone_mask_entries_to_db(gpointer key, gpointer value, gpointer user_data)
2650 {
2651 int imgid = *(int *)user_data;
2652 mask_entry_t *entry = (mask_entry_t *)value;
2653 if(!(entry->mask_type & (DT_MASKS_CLONE | DT_MASKS_NON_CLONE))) add_mask_entry_to_db(imgid, entry);
2654 }
2655
add_mask_entries_to_db(int imgid,GHashTable * mask_entries,int mask_id)2656 static void add_mask_entries_to_db(int imgid, GHashTable *mask_entries, int mask_id)
2657 {
2658 if(mask_id <= 0) return;
2659
2660 // look for mask_id in the hash table
2661 mask_entry_t *entry = (mask_entry_t *)g_hash_table_lookup(mask_entries, &mask_id);
2662
2663 if(!entry) return;
2664
2665 // if it's a group: recurse into the children first
2666 if(entry->mask_type & DT_MASKS_GROUP)
2667 {
2668 dt_masks_point_group_t *group = (dt_masks_point_group_t *)entry->mask_points;
2669 if((int)(entry->mask_nb * sizeof(dt_masks_point_group_t)) != entry->mask_points_len)
2670 {
2671 fprintf(stderr, "[masks] error loading masks from xmp file, bad binary blob size.\n");
2672 return;
2673 }
2674 for(int i = 0; i < entry->mask_nb; i++)
2675 add_mask_entries_to_db(imgid, mask_entries, group[i].formid);
2676 }
2677
2678 add_mask_entry_to_db(imgid, entry);
2679 }
2680
2681 // get MAX multi_priority
_get_max_multi_priority(GList * history,const char * operation)2682 int _get_max_multi_priority(GList *history, const char *operation)
2683 {
2684 int max_prio = 0;
2685
2686 for(GList *iter = history; iter; iter = g_list_next(iter))
2687 {
2688 history_entry_t *entry = (history_entry_t *)iter->data;
2689
2690 if(!strcmp(entry->operation, operation))
2691 max_prio = MAX(max_prio, entry->multi_priority);
2692 }
2693
2694 return max_prio;
2695 }
2696
_image_altered_deprecated(const uint32_t imgid)2697 static gboolean _image_altered_deprecated(const uint32_t imgid)
2698 {
2699 sqlite3_stmt *stmt;
2700
2701 const gboolean basecurve_auto_apply =
2702 dt_conf_is_equal("plugins/darkroom/workflow", "display-referred");
2703
2704 const gboolean sharpen_auto_apply = dt_conf_get_bool("plugins/darkroom/sharpen/auto_apply");
2705
2706 char query[1024] = { 0 };
2707
2708 snprintf(query, sizeof(query),
2709 "SELECT 1"
2710 " FROM main.history, main.images"
2711 " WHERE id=?1 AND imgid=id AND num<history_end AND enabled=1"
2712 " AND operation NOT IN ('flip', 'dither', 'highlights', 'rawprepare',"
2713 " 'colorin', 'colorout', 'gamma', 'demosaic', 'temperature'%s%s)",
2714 basecurve_auto_apply ? ", 'basecurve'" : "",
2715 sharpen_auto_apply ? ", 'sharpen'" : "");
2716
2717 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
2718 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
2719
2720 const gboolean altered = (sqlite3_step(stmt) == SQLITE_ROW);
2721 sqlite3_finalize(stmt);
2722
2723 return altered;
2724 }
2725
2726 // need a write lock on *img (non-const) to write stars (and soon color labels).
dt_exif_xmp_read(dt_image_t * img,const char * filename,const int history_only)2727 int dt_exif_xmp_read(dt_image_t *img, const char *filename, const int history_only)
2728 {
2729 // exclude pfm to avoid stupid errors on the console
2730 const char *c = filename + strlen(filename) - 4;
2731 if(c >= filename && !strcmp(c, ".pfm")) return 1;
2732 try
2733 {
2734 // read xmp sidecar
2735 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
2736 assert(image.get() != 0);
2737 read_metadata_threadsafe(image);
2738 Exiv2::XmpData &xmpData = image->xmpData();
2739
2740 sqlite3_stmt *stmt;
2741
2742 Exiv2::XmpData::iterator pos;
2743
2744 int version = 0;
2745 GList *iop_order_list = NULL;
2746 dt_iop_order_t iop_order_version = DT_IOP_ORDER_LEGACY;
2747
2748 int num_masks = 0;
2749 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.xmp_version"))) != xmpData.end())
2750 version = pos->toLong();
2751
2752 if(!history_only)
2753 {
2754 // otherwise we ignore title, description, ... from non-dt xmp files :(
2755 const size_t ns_pos = image->xmpPacket().find("xmlns:darktable=\"http://darktable.sf.net/\"");
2756 const bool is_a_dt_xmp = (ns_pos != std::string::npos);
2757 _exif_decode_xmp_data(img, xmpData, is_a_dt_xmp ? version : -1, false);
2758 }
2759
2760
2761 // convert legacy flip bits (will not be written anymore, convert to flip history item here):
2762 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.raw_params"))) != xmpData.end())
2763 {
2764 union {
2765 int32_t in;
2766 dt_image_raw_parameters_t out;
2767 } raw_params;
2768 raw_params.in = pos->toLong();
2769 const int32_t user_flip = raw_params.out.user_flip;
2770 img->legacy_flip.user_flip = user_flip;
2771 img->legacy_flip.legacy = 0;
2772 }
2773
2774 int32_t preset_applied = 0;
2775
2776 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.auto_presets_applied"))) != xmpData.end())
2777 {
2778 preset_applied = pos->toLong();
2779
2780 // in any case, this is no legacy image.
2781 img->flags |= DT_IMAGE_NO_LEGACY_PRESETS;
2782 }
2783 else if(xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.xmp_version")) == xmpData.end())
2784 {
2785 // if there is no darktable version in the XMP, this XMP must have been generated by another
2786 // program; since this is the first time darktable sees it, there can't be legacy presets
2787 img->flags |= DT_IMAGE_NO_LEGACY_PRESETS;
2788 }
2789 else
2790 {
2791 // so we are legacy (thus have to clear the no-legacy flag)
2792 img->flags &= ~DT_IMAGE_NO_LEGACY_PRESETS;
2793 }
2794 // when we are reading the xmp data it doesn't make sense to flag the image as removed
2795 img->flags &= ~DT_IMAGE_REMOVE;
2796
2797 if(version == 4)
2798 {
2799 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.iop_order_version"))) != xmpData.end())
2800 {
2801 iop_order_version = (dt_iop_order_t)pos->toLong();
2802 }
2803
2804 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.iop_order_list"))) != xmpData.end())
2805 {
2806 iop_order_list = dt_ioppr_deserialize_text_iop_order_list(pos->toString().c_str());
2807 }
2808 else
2809 iop_order_list = dt_ioppr_get_iop_order_list_version(iop_order_version);
2810 }
2811 else if(version == 3)
2812 {
2813 iop_order_version = DT_IOP_ORDER_LEGACY;
2814
2815 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.iop_order_version"))) != xmpData.end())
2816 {
2817 // All iop-order version before 3 are legacy one. Starting with version 3 we have the first
2818 // attempts to propose the final v3 iop-order.
2819 iop_order_version = pos->toLong() < 3 ? DT_IOP_ORDER_LEGACY : DT_IOP_ORDER_V30;
2820 iop_order_list = dt_ioppr_get_iop_order_list_version(iop_order_version);
2821 }
2822 else
2823 iop_order_list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_LEGACY);
2824 }
2825 else
2826 {
2827 iop_order_version = DT_IOP_ORDER_LEGACY;
2828 iop_order_list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_LEGACY);
2829 }
2830
2831 // masks
2832 GHashTable *mask_entries = NULL;
2833 GList *mask_entries_v3 = NULL;
2834
2835 // clean all old masks for this image
2836 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM main.masks_history WHERE imgid = ?1", -1,
2837 &stmt, NULL);
2838 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
2839 sqlite3_step(stmt);
2840 sqlite3_finalize(stmt);
2841
2842 // read the masks from the file first so we can add them to the db while reading history entries
2843 if(version < 3)
2844 mask_entries = read_masks(xmpData, filename, version);
2845 else
2846 mask_entries_v3 = read_masks_v3(xmpData, filename, version);
2847
2848 // now add all masks that are not used for cloning. keeping them might be useful.
2849 // TODO: make this configurable? or remove it altogether?
2850 sqlite3_exec(dt_database_get(darktable.db), "BEGIN TRANSACTION", NULL, NULL, NULL);
2851 if(version < 3)
2852 {
2853 g_hash_table_foreach(mask_entries, add_non_clone_mask_entries_to_db, &img->id);
2854 }
2855 else
2856 {
2857 for(GList *m_entries = g_list_first(mask_entries_v3); m_entries; m_entries = g_list_next(m_entries))
2858 {
2859 mask_entry_t *mask_entry = (mask_entry_t *)m_entries->data;
2860
2861 add_mask_entry_to_db(img->id, mask_entry);
2862 }
2863 }
2864 sqlite3_exec(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
2865
2866 // history
2867 int num = 0;
2868 gboolean all_ok = TRUE;
2869 GList *history_entries = NULL;
2870
2871 if(version < 2)
2872 {
2873 std::string &xmpPacket = image->xmpPacket();
2874 history_entries = read_history_v1(xmpPacket, filename, 0);
2875 if(!history_entries) // didn't work? try super old version with rdf:Bag
2876 history_entries = read_history_v1(xmpPacket, filename, 1);
2877 }
2878 else if(version == 2 || version == 3 || version == 4)
2879 history_entries = read_history_v2(xmpData, filename);
2880 else
2881 {
2882 std::cerr << "error: Xmp schema version " << version << " in " << filename << " not supported" << std::endl;
2883 g_hash_table_destroy(mask_entries);
2884 return 1;
2885 }
2886
2887 sqlite3_exec(dt_database_get(darktable.db), "BEGIN TRANSACTION", NULL, NULL, NULL);
2888
2889 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "DELETE FROM main.history WHERE imgid = ?1", -1,
2890 &stmt, NULL);
2891 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
2892 if(sqlite3_step(stmt) != SQLITE_DONE)
2893 {
2894 fprintf(stderr, "[exif] error deleting history for image %d\n", img->id);
2895 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
2896 all_ok = FALSE;
2897 goto end;
2898 }
2899 sqlite3_finalize(stmt);
2900
2901 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
2902 "INSERT INTO main.history"
2903 " (imgid, num, module, operation, op_params, enabled, "
2904 " blendop_params, blendop_version, multi_priority, multi_name) "
2905 "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)", -1, &stmt, NULL);
2906
2907 for(GList *iter = history_entries; iter; iter = g_list_next(iter))
2908 {
2909 history_entry_t *entry = (history_entry_t *)iter->data;
2910
2911 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
2912 if(version < 3)
2913 {
2914 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, num);
2915 }
2916 else
2917 {
2918 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, entry->num);
2919 }
2920 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, entry->modversion);
2921 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, entry->operation, -1, SQLITE_TRANSIENT);
2922 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 5, entry->params, entry->params_len, SQLITE_TRANSIENT);
2923 DT_DEBUG_SQLITE3_BIND_INT(stmt, 6, entry->enabled);
2924 if(entry->blendop_params)
2925 {
2926 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 7, entry->blendop_params, entry->blendop_params_len, SQLITE_TRANSIENT);
2927
2928 if(version < 3)
2929 {
2930 // check what mask entries belong to this iop and add them to the db
2931 const dt_develop_blend_params_t *blendop_params = (dt_develop_blend_params_t *)entry->blendop_params;
2932 add_mask_entries_to_db(img->id, mask_entries, blendop_params->mask_id);
2933 }
2934 }
2935 else
2936 {
2937 sqlite3_bind_null(stmt, 7);
2938 }
2939 DT_DEBUG_SQLITE3_BIND_INT(stmt, 8, entry->blendop_version);
2940 DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, entry->multi_priority);
2941 if(entry->multi_name)
2942 {
2943 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 10, entry->multi_name, -1, SQLITE_TRANSIENT);
2944 }
2945 else
2946 {
2947 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 10, "", -1, SQLITE_TRANSIENT); // "" instead of " " should be fine now
2948 }
2949
2950 if(sqlite3_step(stmt) != SQLITE_DONE)
2951 {
2952 fprintf(stderr, "[exif] error adding history entry for image %d\n", img->id);
2953 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
2954 all_ok = FALSE;
2955 goto end;
2956 }
2957 sqlite3_reset(stmt);
2958 sqlite3_clear_bindings(stmt);
2959
2960 num++;
2961 }
2962 sqlite3_finalize(stmt);
2963
2964 // we now need to create and store the proper iop-order taking into account all multi-instances
2965 // for previous xmp versions.
2966
2967 if(version < 4)
2968 {
2969 // in this version we had iop-order, use it
2970
2971 for(GList *iter = history_entries; iter; iter = g_list_next(iter))
2972 {
2973 history_entry_t *entry = (history_entry_t *)iter->data;
2974
2975 dt_iop_order_entry_t *e = (dt_iop_order_entry_t *)malloc(sizeof(dt_iop_order_entry_t));
2976 memcpy(e->operation, entry->operation, sizeof(e->operation));
2977 e->instance = entry->multi_priority;
2978
2979 if(version < 3)
2980 {
2981 // prior to v3 there was no iop-order, all multi instances where grouped, use the multièpriority
2982 // to restore the order.
2983 GList *base_order = dt_ioppr_get_iop_order_link(iop_order_list, entry->operation, -1);
2984
2985 if(base_order)
2986 e->o.iop_order_f = ((dt_iop_order_entry_t *)(base_order->data))->o.iop_order_f
2987 - entry->multi_priority / 100.0f;
2988 else
2989 {
2990 fprintf(stderr,
2991 "[exif] cannot get iop-order for module '%s', XMP may be corrupted\n",
2992 entry->operation);
2993 g_list_free_full(iop_order_list, free);
2994 g_list_free_full(history_entries, free_history_entry);
2995 g_list_free_full(mask_entries_v3, free_mask_entry);
2996 if(mask_entries) g_hash_table_destroy(mask_entries);
2997 g_free(e);
2998 return 1;
2999 }
3000 }
3001 else
3002 {
3003 // otherwise use the iop_order for the entry
3004 e->o.iop_order_f = entry->iop_order; // legacy iop-order is used to insert item at the right location
3005 }
3006
3007 // remove a current entry from the iop-order list if found as it will be replaced, possibly with another iop-order
3008 // with a new item in the history.
3009
3010 GList *link = dt_ioppr_get_iop_order_link(iop_order_list, e->operation, e->instance);
3011 if(link) iop_order_list = g_list_delete_link(iop_order_list, link);
3012
3013 iop_order_list = g_list_append(iop_order_list, e);
3014 }
3015
3016 // and finally reorder the full list based on the iop-order
3017
3018 iop_order_list = g_list_sort(iop_order_list, dt_sort_iop_list_by_order_f);
3019 }
3020
3021 // if masks have been read, create a mask manager entry in history
3022 if(version < 3)
3023 {
3024 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3025 "SELECT COUNT(*) FROM main.masks_history WHERE imgid = ?1", -1,
3026 &stmt, NULL);
3027 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
3028 if(sqlite3_step(stmt) == SQLITE_ROW)
3029 num_masks = sqlite3_column_int(stmt, 0);
3030 sqlite3_finalize(stmt);
3031
3032 if(num_masks > 0)
3033 {
3034 // make room for mask_manager entry
3035 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3036 "UPDATE main.history SET num = num + 1 WHERE imgid = ?1", -1,
3037 &stmt, NULL);
3038 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
3039 sqlite3_step(stmt);
3040 sqlite3_finalize(stmt);
3041
3042 // insert mask_manager entry
3043
3044 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3045 "INSERT INTO main.history"
3046 " (imgid, num, module, operation, op_params, enabled, "
3047 " blendop_params, blendop_version, multi_priority, multi_name) "
3048 "VALUES"
3049 " (?1, 0, 1, 'mask_manager', NULL, 0, NULL, 0, 0, '')", -1, &stmt, NULL);
3050 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
3051 if(sqlite3_step(stmt) != SQLITE_DONE)
3052 {
3053 fprintf(stderr, "[exif] error adding mask history entry for image %d\n", img->id);
3054 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
3055 all_ok = FALSE;
3056 goto end;
3057 }
3058 sqlite3_finalize(stmt);
3059
3060 num++;
3061 }
3062 }
3063
3064 // we shouldn't change history_end when no history was read!
3065 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.history_end"))) != xmpData.end() && num > 0)
3066 {
3067 int history_end = MIN(pos->toLong(), num);
3068 if(num_masks > 0) history_end++;
3069 if((history_end < 1) && preset_applied) preset_applied = -1;
3070 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3071 "UPDATE main.images SET history_end = ?1 WHERE id = ?2", -1,
3072 &stmt, NULL);
3073 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, history_end);
3074 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, img->id);
3075 if(sqlite3_step(stmt) != SQLITE_DONE)
3076 {
3077 fprintf(stderr, "[exif] error writing history_end for image %d\n", img->id);
3078 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
3079 all_ok = FALSE;
3080 goto end;
3081 }
3082 }
3083 else
3084 {
3085 if(preset_applied) preset_applied = -1;
3086 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3087 "UPDATE main.images "
3088 " SET history_end = (SELECT IFNULL(MAX(num) + 1, 0)"
3089 " FROM main.history"
3090 " WHERE imgid = ?1)"
3091 " WHERE id = ?1", -1,
3092 &stmt, NULL);
3093 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->id);
3094 if(sqlite3_step(stmt) != SQLITE_DONE)
3095 {
3096 fprintf(stderr, "[exif] error writing history_end for image %d\n", img->id);
3097 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
3098 all_ok = FALSE;
3099 goto end;
3100 }
3101 }
3102 if(!dt_ioppr_write_iop_order_list(iop_order_list, img->id))
3103 {
3104 fprintf(stderr, "[exif] error writing iop_list for image %d\n", img->id);
3105 fprintf(stderr, "[exif] %s\n", sqlite3_errmsg(dt_database_get(darktable.db)));
3106 all_ok = FALSE;
3107 goto end;
3108 }
3109
3110 end:
3111
3112 read_xmp_timestamps(xmpData, img);
3113
3114 sqlite3_finalize(stmt);
3115
3116 // set or clear bit in image struct. ONLY set if the Xmp.darktable.auto_presets_applied was 1
3117 // AND there was a history in xmp
3118 if(preset_applied > 0)
3119 {
3120 img->flags |= DT_IMAGE_AUTO_PRESETS_APPLIED;
3121 }
3122 else
3123 {
3124 // not found for old or buggy xmp where it was found but history was 0
3125 img->flags &= ~DT_IMAGE_AUTO_PRESETS_APPLIED;
3126
3127 if(preset_applied < 0)
3128 {
3129 fprintf(stderr,"[exif] dt_exif_xmp_read for %s, id %i found auto_presets_applied but there was no history\n",filename,img->id);
3130 }
3131 }
3132
3133 g_list_free_full(iop_order_list, free);
3134 g_list_free_full(history_entries, free_history_entry);
3135 g_list_free_full(mask_entries_v3, free_mask_entry);
3136 if(mask_entries) g_hash_table_destroy(mask_entries);
3137
3138 if(all_ok)
3139 {
3140 sqlite3_exec(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
3141
3142 // history_hash
3143 dt_history_hash_values_t hash = {NULL, 0, NULL, 0, NULL, 0};
3144 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.history_basic_hash"))) != xmpData.end())
3145 {
3146 hash.basic = dt_exif_xmp_decode(pos->toString().c_str(), strlen(pos->toString().c_str()),
3147 &hash.basic_len);
3148 }
3149 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.history_auto_hash"))) != xmpData.end())
3150 {
3151 hash.auto_apply = dt_exif_xmp_decode(pos->toString().c_str(), strlen(pos->toString().c_str()),
3152 &hash.auto_apply_len);
3153 }
3154 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.history_current_hash"))) != xmpData.end())
3155 {
3156 hash.current = dt_exif_xmp_decode(pos->toString().c_str(), strlen(pos->toString().c_str()),
3157 &hash.current_len);
3158 }
3159 if(hash.basic || hash.auto_apply || hash.current)
3160 {
3161 dt_history_hash_write(img->id, &hash);
3162 }
3163 else
3164 {
3165 // no choice, use the history itelf applying the former rules
3166 dt_history_hash_t hash_flag = DT_HISTORY_HASH_CURRENT;
3167 if(!_image_altered_deprecated(img->id))
3168 // we assume the image has an history
3169 hash_flag = (dt_history_hash_t)(hash_flag | DT_HISTORY_HASH_BASIC);
3170 dt_history_hash_write_from_history(img->id, hash_flag);
3171 }
3172 }
3173 else
3174 {
3175 std::cerr << "[exif] error reading history from '" << filename << "'" << std::endl;
3176 sqlite3_exec(dt_database_get(darktable.db), "ROLLBACK TRANSACTION", NULL, NULL, NULL);
3177 return 1;
3178 }
3179
3180 }
3181 catch(Exiv2::AnyError &e)
3182 {
3183 // actually nobody's interested in that if the file doesn't exist:
3184 // std::string s(e.what());
3185 // std::cerr << "[exiv2] " << filename << ": " << s << std::endl;
3186 return 1;
3187 }
3188 return 0;
3189 }
3190
3191 // add history metadata to XmpData
dt_set_xmp_dt_history(Exiv2::XmpData & xmpData,const int imgid,int history_end)3192 static void dt_set_xmp_dt_history(Exiv2::XmpData &xmpData, const int imgid, int history_end)
3193 {
3194 sqlite3_stmt *stmt;
3195
3196 // masks:
3197 char key[1024];
3198 int num = 1;
3199
3200 // masks history:
3201 num = 1;
3202
3203 // create an array:
3204 Exiv2::XmpTextValue tvm("");
3205 tvm.setXmpArrayType(Exiv2::XmpValue::xaSeq);
3206 xmpData.add(Exiv2::XmpKey("Xmp.darktable.masks_history"), &tvm);
3207
3208 DT_DEBUG_SQLITE3_PREPARE_V2(
3209 dt_database_get(darktable.db),
3210 "SELECT imgid, formid, form, name, version, points, points_count, source, num"
3211 " FROM main.masks_history"
3212 " WHERE imgid = ?1"
3213 " ORDER BY num",
3214 -1, &stmt, NULL);
3215 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3216 while(sqlite3_step(stmt) == SQLITE_ROW)
3217 {
3218 const int32_t mask_num = sqlite3_column_int(stmt, 8);
3219 const int32_t mask_id = sqlite3_column_int(stmt, 1);
3220 const int32_t mask_type = sqlite3_column_int(stmt, 2);
3221 const char *mask_name = (const char *)sqlite3_column_text(stmt, 3);
3222 const int32_t mask_version = sqlite3_column_int(stmt, 4);
3223 int32_t len = sqlite3_column_bytes(stmt, 5);
3224 char *mask_d = dt_exif_xmp_encode((const unsigned char *)sqlite3_column_blob(stmt, 5), len, NULL);
3225 const int32_t mask_nb = sqlite3_column_int(stmt, 6);
3226 len = sqlite3_column_bytes(stmt, 7);
3227 char *mask_src = dt_exif_xmp_encode((const unsigned char *)sqlite3_column_blob(stmt, 7), len, NULL);
3228
3229 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_num", num);
3230 xmpData[key] = mask_num;
3231 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_id", num);
3232 xmpData[key] = mask_id;
3233 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_type", num);
3234 xmpData[key] = mask_type;
3235 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_name", num);
3236 xmpData[key] = mask_name;
3237 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_version", num);
3238 xmpData[key] = mask_version;
3239 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_points", num);
3240 xmpData[key] = mask_d;
3241 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_nb", num);
3242 xmpData[key] = mask_nb;
3243 snprintf(key, sizeof(key), "Xmp.darktable.masks_history[%d]/darktable:mask_src", num);
3244 xmpData[key] = mask_src;
3245
3246 free(mask_d);
3247 free(mask_src);
3248
3249 num++;
3250 }
3251 sqlite3_finalize(stmt);
3252
3253 // history stack:
3254 num = 1;
3255
3256 // create an array:
3257 Exiv2::XmpTextValue tv("");
3258 tv.setXmpArrayType(Exiv2::XmpValue::xaSeq);
3259 xmpData.add(Exiv2::XmpKey("Xmp.darktable.history"), &tv);
3260
3261 DT_DEBUG_SQLITE3_PREPARE_V2(
3262 dt_database_get(darktable.db),
3263 "SELECT module, operation, op_params, enabled, blendop_params, "
3264 " blendop_version, multi_priority, multi_name, num"
3265 " FROM main.history"
3266 " WHERE imgid = ?1"
3267 " ORDER BY num",
3268 -1, &stmt, NULL);
3269 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3270 while(sqlite3_step(stmt) == SQLITE_ROW)
3271 {
3272 int32_t modversion = sqlite3_column_int(stmt, 0);
3273 const char *operation = (const char *)sqlite3_column_text(stmt, 1);
3274 int32_t params_len = sqlite3_column_bytes(stmt, 2);
3275 const void *params_blob = sqlite3_column_blob(stmt, 2);
3276 const int32_t enabled = sqlite3_column_int(stmt, 3);
3277 const void *blendop_blob = sqlite3_column_blob(stmt, 4);
3278 int32_t blendop_params_len = sqlite3_column_bytes(stmt, 4);
3279 int32_t blendop_version = sqlite3_column_int(stmt, 5);
3280 int32_t multi_priority = sqlite3_column_int(stmt, 6);
3281 const char *multi_name = (const char *)sqlite3_column_text(stmt, 7);
3282 int32_t hist_num = sqlite3_column_int(stmt, 8);
3283
3284 if(!operation) continue; // no op is fatal.
3285
3286 char *params = dt_exif_xmp_encode((const unsigned char *)params_blob, params_len, NULL);
3287
3288 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:num", num);
3289 xmpData[key] = hist_num;
3290 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:operation", num);
3291 xmpData[key] = operation;
3292 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:enabled", num);
3293 xmpData[key] = enabled;
3294 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:modversion", num);
3295 xmpData[key] = modversion;
3296 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:params", num);
3297 xmpData[key] = params;
3298 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:multi_name", num);
3299 xmpData[key] = multi_name ? multi_name : "";
3300 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:multi_priority", num);
3301 xmpData[key] = multi_priority;
3302
3303 if(blendop_blob)
3304 {
3305 // this shouldn't fail in general, but reading is robust enough to allow it,
3306 // and flipping images from LT will result in this being left out
3307 char *blendop_params = dt_exif_xmp_encode((const unsigned char *)blendop_blob, blendop_params_len, NULL);
3308 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:blendop_version", num);
3309 xmpData[key] = blendop_version;
3310 snprintf(key, sizeof(key), "Xmp.darktable.history[%d]/darktable:blendop_params", num);
3311 xmpData[key] = blendop_params;
3312 free(blendop_params);
3313 }
3314
3315 free(params);
3316
3317 num++;
3318 }
3319
3320 sqlite3_finalize(stmt);
3321 if(history_end == -1) history_end = num - 1;
3322 else history_end = MIN(history_end, num - 1); // safeguard for some old buggy libraries
3323 xmpData["Xmp.darktable.history_end"] = history_end;
3324 }
3325
3326 // add timestamps to XmpData.
set_xmp_timestamps(Exiv2::XmpData & xmpData,const int imgid)3327 static void set_xmp_timestamps(Exiv2::XmpData &xmpData, const int imgid)
3328 {
3329 sqlite3_stmt *stmt;
3330
3331 DT_DEBUG_SQLITE3_PREPARE_V2(
3332 dt_database_get(darktable.db),
3333 "SELECT import_timestamp, change_timestamp, export_timestamp, print_timestamp"
3334 " FROM main.images"
3335 " WHERE id = ?1",
3336 -1, &stmt, NULL);
3337 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3338
3339 if(sqlite3_step(stmt) == SQLITE_ROW)
3340 {
3341 xmpData["Xmp.darktable.import_timestamp"] = sqlite3_column_int(stmt, 0);
3342 xmpData["Xmp.darktable.change_timestamp"] = sqlite3_column_int(stmt, 1);
3343 xmpData["Xmp.darktable.export_timestamp"] = sqlite3_column_int(stmt, 2);
3344 xmpData["Xmp.darktable.print_timestamp"] = sqlite3_column_int(stmt, 3);
3345 }
3346 else
3347 {
3348 xmpData["Xmp.darktable.import_timestamp"] = -1;
3349 xmpData["Xmp.darktable.change_timestamp"] = -1;
3350 xmpData["Xmp.darktable.export_timestamp"] = -1;
3351 xmpData["Xmp.darktable.print_timestamp"] = -1;
3352 }
3353 sqlite3_finalize(stmt);
3354 }
3355
3356 // read timestamps from XmpData
read_xmp_timestamps(Exiv2::XmpData & xmpData,dt_image_t * img)3357 void read_xmp_timestamps(Exiv2::XmpData &xmpData, dt_image_t *img)
3358 {
3359 Exiv2::XmpData::iterator pos;
3360
3361 // Do not read for import_ts. It must be updated at each import.
3362 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.change_timestamp"))) != xmpData.end())
3363 {
3364 img->change_timestamp = pos->toLong();
3365 }
3366 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.export_timestamp"))) != xmpData.end())
3367 {
3368 img->export_timestamp = pos->toLong();
3369 }
3370 if((pos = xmpData.findKey(Exiv2::XmpKey("Xmp.darktable.print_timestamp"))) != xmpData.end())
3371 {
3372 img->print_timestamp = pos->toLong();
3373 }
3374 }
3375
dt_remove_xmp_exif_geotag(Exiv2::XmpData & xmpData)3376 static void dt_remove_xmp_exif_geotag(Exiv2::XmpData &xmpData)
3377 {
3378 static const char *keys[] =
3379 {
3380 "Xmp.exif.GPSVersionID",
3381 "Xmp.exif.GPSLongitude",
3382 "Xmp.exif.GPSLatitude",
3383 "Xmp.exif.GPSAltitudeRef",
3384 "Xmp.exif.GPSAltitude"
3385 };
3386 static const guint n_keys = G_N_ELEMENTS(keys);
3387 dt_remove_xmp_keys(xmpData, keys, n_keys);
3388 }
3389
dt_set_xmp_exif_geotag(Exiv2::XmpData & xmpData,double longitude,double latitude,double altitude)3390 static void dt_set_xmp_exif_geotag(Exiv2::XmpData &xmpData, double longitude, double latitude, double altitude)
3391 {
3392 dt_remove_xmp_exif_geotag(xmpData);
3393 if(!std::isnan(longitude) && !std::isnan(latitude))
3394 {
3395 char long_dir = 'E', lat_dir = 'N';
3396 if(longitude < 0) long_dir = 'W';
3397 if(latitude < 0) lat_dir = 'S';
3398
3399 longitude = fabs(longitude);
3400 latitude = fabs(latitude);
3401
3402 int long_deg = (int)floor(longitude);
3403 int lat_deg = (int)floor(latitude);
3404 double long_min = (longitude - (double)long_deg) * 60.0;
3405 double lat_min = (latitude - (double)lat_deg) * 60.0;
3406
3407 char *str = (char *)g_malloc(G_ASCII_DTOSTR_BUF_SIZE);
3408
3409 g_ascii_formatd(str, G_ASCII_DTOSTR_BUF_SIZE, "%08f", long_min);
3410 gchar *long_str = g_strdup_printf("%d,%s%c", long_deg, str, long_dir);
3411 g_ascii_formatd(str, G_ASCII_DTOSTR_BUF_SIZE, "%08f", lat_min);
3412 gchar *lat_str = g_strdup_printf("%d,%s%c", lat_deg, str, lat_dir);
3413
3414 xmpData["Xmp.exif.GPSVersionID"] = "2.2.0.0";
3415 xmpData["Xmp.exif.GPSLongitude"] = long_str;
3416 xmpData["Xmp.exif.GPSLatitude"] = lat_str;
3417 g_free(long_str);
3418 g_free(lat_str);
3419 g_free(str);
3420 }
3421 if(!std::isnan(altitude))
3422 {
3423 xmpData["Xmp.exif.GPSAltitudeRef"] = (altitude < 0) ? "1" : "0";
3424
3425 long ele_dm = (int)floor(fabs(10.0 * altitude));
3426 gchar *ele_str = g_strdup_printf("%ld/10", ele_dm);
3427 xmpData["Xmp.exif.GPSAltitude"] = ele_str;
3428 g_free(ele_str);
3429 }
3430 }
3431
dt_set_xmp_dt_metadata(Exiv2::XmpData & xmpData,const int imgid,const gboolean export_flag)3432 static void dt_set_xmp_dt_metadata(Exiv2::XmpData &xmpData, const int imgid, const gboolean export_flag)
3433 {
3434 sqlite3_stmt *stmt;
3435 // metadata
3436 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT key, value FROM main.meta_data WHERE id = ?1",
3437 -1, &stmt, NULL);
3438 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3439 while(sqlite3_step(stmt) == SQLITE_ROW)
3440 {
3441 int keyid = sqlite3_column_int(stmt, 0);
3442 if(export_flag && (dt_metadata_get_type(keyid) != DT_METADATA_TYPE_INTERNAL))
3443 {
3444 const gchar *name = dt_metadata_get_name(keyid);
3445 gchar *setting = dt_util_dstrcat(NULL, "plugins/lighttable/metadata/%s_flag", name);
3446 const uint32_t flag = dt_conf_get_int(setting);
3447 g_free(setting);
3448 if(!(flag & (DT_METADATA_FLAG_PRIVATE | DT_METADATA_FLAG_HIDDEN)))
3449 xmpData[dt_metadata_get_key(keyid)] = sqlite3_column_text(stmt, 1);
3450 }
3451 else
3452 xmpData[dt_metadata_get_key(keyid)] = sqlite3_column_text(stmt, 1);
3453 }
3454 sqlite3_finalize(stmt);
3455
3456 // color labels
3457 char val[2048];
3458 std::unique_ptr<Exiv2::Value> v(Exiv2::Value::create(Exiv2::xmpSeq)); // or xmpBag or xmpAlt.
3459
3460 /* Already initialized v = Exiv2::Value::create(Exiv2::xmpSeq); // or xmpBag or xmpAlt.*/
3461 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT color FROM main.color_labels WHERE imgid=?1",
3462 -1, &stmt, NULL);
3463 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3464 while(sqlite3_step(stmt) == SQLITE_ROW)
3465 {
3466 snprintf(val, sizeof(val), "%d", sqlite3_column_int(stmt, 0));
3467 v->read(val);
3468 }
3469 sqlite3_finalize(stmt);
3470 if(v->count() > 0) xmpData.add(Exiv2::XmpKey("Xmp.darktable.colorlabels"), v.get());
3471 }
3472
3473 // helper to create an xmp data thing. throws exiv2 exceptions if stuff goes wrong.
_exif_xmp_read_data(Exiv2::XmpData & xmpData,const int imgid)3474 static void _exif_xmp_read_data(Exiv2::XmpData &xmpData, const int imgid)
3475 {
3476 const int xmp_version = DT_XMP_EXIF_VERSION;
3477 int stars = 1, raw_params = 0, history_end = -1;
3478 double longitude = NAN, latitude = NAN, altitude = NAN;
3479 gchar *filename = NULL;
3480 gchar *datetime_taken = NULL;
3481 gchar *iop_order_list = NULL;
3482
3483 // get stars and raw params from db
3484 sqlite3_stmt *stmt;
3485 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3486 "SELECT filename, flags, raw_parameters, "
3487 " longitude, latitude, altitude, history_end, datetime_taken"
3488 " FROM main.images"
3489 " WHERE id = ?1",
3490 -1, &stmt, NULL);
3491 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3492 if(sqlite3_step(stmt) == SQLITE_ROW)
3493 {
3494 filename = (gchar *)sqlite3_column_text(stmt, 0);
3495 stars = sqlite3_column_int(stmt, 1);
3496 raw_params = sqlite3_column_int(stmt, 2);
3497 if(sqlite3_column_type(stmt, 3) == SQLITE_FLOAT) longitude = sqlite3_column_double(stmt, 3);
3498 if(sqlite3_column_type(stmt, 4) == SQLITE_FLOAT) latitude = sqlite3_column_double(stmt, 4);
3499 if(sqlite3_column_type(stmt, 5) == SQLITE_FLOAT) altitude = sqlite3_column_double(stmt, 5);
3500 history_end = sqlite3_column_int(stmt, 6);
3501 datetime_taken = (gchar *)sqlite3_column_text(stmt, 7);
3502 }
3503
3504 // get iop-order list
3505 const dt_iop_order_t iop_order_version = dt_ioppr_get_iop_order_version(imgid);
3506 GList *iop_list = dt_ioppr_get_iop_order_list(imgid, TRUE);
3507
3508 if(iop_order_version == DT_IOP_ORDER_CUSTOM || dt_ioppr_has_multiple_instances(iop_list))
3509 {
3510 iop_order_list = dt_ioppr_serialize_text_iop_order_list(iop_list);
3511 }
3512 g_list_free_full(iop_list, free);
3513
3514 // Store datetime_taken as DateTimeOriginal to take into account the user's selected date/time
3515 xmpData["Xmp.exif.DateTimeOriginal"] = datetime_taken;
3516
3517 // We have to erase the old ratings first as exiv2 seems to not change it otherwise.
3518 Exiv2::XmpData::iterator pos = xmpData.findKey(Exiv2::XmpKey("Xmp.xmp.Rating"));
3519 if(pos != xmpData.end()) xmpData.erase(pos);
3520 xmpData["Xmp.xmp.Rating"] = dt_image_get_xmp_rating_from_flags(stars);
3521
3522 // The original file name
3523 if(filename) xmpData["Xmp.xmpMM.DerivedFrom"] = filename;
3524
3525 // timestamps
3526 set_xmp_timestamps(xmpData, imgid);
3527
3528 // GPS data
3529 dt_set_xmp_exif_geotag(xmpData, longitude, latitude, altitude);
3530
3531 // the meta data
3532 dt_set_xmp_dt_metadata(xmpData, imgid, FALSE);
3533
3534 // get tags from db, store in dublin core
3535 std::unique_ptr<Exiv2::Value> v1(Exiv2::Value::create(Exiv2::xmpBag));
3536
3537 std::unique_ptr<Exiv2::Value> v2(Exiv2::Value::create(Exiv2::xmpBag));
3538
3539 GList *tags = dt_tag_get_list(imgid);
3540 for(GList *tag = tags; tag; tag = g_list_next(tag))
3541 {
3542 v1->read((char *)tag->data);
3543 }
3544 if(v1->count() > 0) xmpData.add(Exiv2::XmpKey("Xmp.dc.subject"), v1.get());
3545 g_list_free_full(tags, g_free);
3546
3547 GList *hierarchical = dt_tag_get_hierarchical(imgid);
3548 for(GList *hier = hierarchical; hier; hier = g_list_next(hier))
3549 {
3550 v2->read((char *)hier->data);
3551 }
3552 if(v2->count() > 0) xmpData.add(Exiv2::XmpKey("Xmp.lr.hierarchicalSubject"), v2.get());
3553 g_list_free_full(hierarchical, g_free);
3554 /* TODO: Add tags to IPTC namespace as well */
3555
3556 xmpData["Xmp.darktable.xmp_version"] = xmp_version;
3557 xmpData["Xmp.darktable.raw_params"] = raw_params;
3558 if(stars & DT_IMAGE_AUTO_PRESETS_APPLIED)
3559 xmpData["Xmp.darktable.auto_presets_applied"] = 1;
3560 else
3561 xmpData["Xmp.darktable.auto_presets_applied"] = 0;
3562 dt_set_xmp_dt_history(xmpData, imgid, history_end);
3563
3564 // we need to read the iop-order list
3565 xmpData["Xmp.darktable.iop_order_version"] = iop_order_version;
3566 if(iop_order_list) xmpData["Xmp.darktable.iop_order_list"] = iop_order_list;
3567
3568 sqlite3_finalize(stmt);
3569 g_free(iop_order_list);
3570
3571 // store history hash
3572 dt_history_hash_values_t hash;
3573 dt_history_hash_read(imgid, &hash);
3574 if(hash.basic)
3575 {
3576 char* value = dt_exif_xmp_encode(hash.basic, hash.basic_len, NULL);
3577 xmpData["Xmp.darktable.history_basic_hash"] = value;
3578 free(value);
3579 g_free(hash.basic);
3580 }
3581 if(hash.auto_apply)
3582 {
3583 char* value = dt_exif_xmp_encode(hash.auto_apply, hash.auto_apply_len, NULL);
3584 xmpData["Xmp.darktable.history_auto_hash"] = value;
3585 free(value);
3586 g_free(hash.auto_apply);
3587 }
3588 if(hash.current)
3589 {
3590 char* value = dt_exif_xmp_encode(hash.current, hash.current_len, NULL);
3591 xmpData["Xmp.darktable.history_current_hash"] = value;
3592 free(value);
3593 g_free(hash.current);
3594 }
3595 }
3596
3597 // helper to create an xmp data thing. throws exiv2 exceptions if stuff goes wrong.
_exif_xmp_read_data_export(Exiv2::XmpData & xmpData,const int imgid,dt_export_metadata_t * metadata)3598 static void _exif_xmp_read_data_export(Exiv2::XmpData &xmpData, const int imgid, dt_export_metadata_t *metadata)
3599 {
3600 const int xmp_version = DT_XMP_EXIF_VERSION;
3601 int stars = 1, raw_params = 0, history_end = -1;
3602 double longitude = NAN, latitude = NAN, altitude = NAN;
3603 gchar *filename = NULL;
3604 gchar *datetime_taken = NULL;
3605 gchar *iop_order_list = NULL;
3606
3607 // get stars and raw params from db
3608 sqlite3_stmt *stmt;
3609 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
3610 "SELECT filename, flags, raw_parameters, "
3611 " longitude, latitude, altitude, history_end, datetime_taken"
3612 " FROM main.images"
3613 " WHERE id = ?1",
3614 -1, &stmt, NULL);
3615 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
3616 if(sqlite3_step(stmt) == SQLITE_ROW)
3617 {
3618 filename = (gchar *)sqlite3_column_text(stmt, 0);
3619 stars = sqlite3_column_int(stmt, 1);
3620 raw_params = sqlite3_column_int(stmt, 2);
3621 if(sqlite3_column_type(stmt, 3) == SQLITE_FLOAT) longitude = sqlite3_column_double(stmt, 3);
3622 if(sqlite3_column_type(stmt, 4) == SQLITE_FLOAT) latitude = sqlite3_column_double(stmt, 4);
3623 if(sqlite3_column_type(stmt, 5) == SQLITE_FLOAT) altitude = sqlite3_column_double(stmt, 5);
3624 history_end = sqlite3_column_int(stmt, 6);
3625 datetime_taken = (gchar *)sqlite3_column_text(stmt, 7);
3626 }
3627
3628 // get iop-order list
3629 const dt_iop_order_t iop_order_version = dt_ioppr_get_iop_order_version(imgid);
3630 GList *iop_list = dt_ioppr_get_iop_order_list(imgid, TRUE);
3631
3632 if(iop_order_version == DT_IOP_ORDER_CUSTOM || dt_ioppr_has_multiple_instances(iop_list))
3633 {
3634 iop_order_list = dt_ioppr_serialize_text_iop_order_list(iop_list);
3635 }
3636 g_list_free_full(iop_list, free);
3637
3638 if(metadata->flags & DT_META_METADATA)
3639 {
3640 // Store datetime_taken as DateTimeOriginal to take into account the user's selected date/time
3641 if (!(metadata->flags & DT_META_EXIF))
3642 xmpData["Xmp.exif.DateTimeOriginal"] = datetime_taken;
3643
3644 // We have to erase the old ratings first as exiv2 seems to not change it otherwise.
3645 Exiv2::XmpData::iterator pos = xmpData.findKey(Exiv2::XmpKey("Xmp.xmp.Rating"));
3646 if(pos != xmpData.end()) xmpData.erase(pos);
3647 xmpData["Xmp.xmp.Rating"] = dt_image_get_xmp_rating_from_flags(stars);
3648
3649 // The original file name
3650 if(filename) xmpData["Xmp.xmpMM.DerivedFrom"] = filename;
3651 }
3652
3653 // GPS data
3654 if (metadata->flags & DT_META_GEOTAG)
3655 dt_set_xmp_exif_geotag(xmpData, longitude, latitude, altitude);
3656 else
3657 dt_remove_xmp_exif_geotag(xmpData);
3658
3659
3660 // the meta data
3661 if (metadata->flags & DT_META_METADATA)
3662 dt_set_xmp_dt_metadata(xmpData, imgid, TRUE);
3663
3664 // tags
3665 if (metadata->flags & DT_META_TAG)
3666 {
3667 // get tags from db, store in dublin core
3668 std::unique_ptr<Exiv2::Value> v1(Exiv2::Value::create(Exiv2::xmpBag));
3669 GList *tags = dt_tag_get_list_export(imgid, metadata->flags);
3670 for(GList *tag = tags; tag; tag = g_list_next(tag))
3671 {
3672 v1->read((char *)tag->data);
3673 }
3674 if(v1->count() > 0) xmpData.add(Exiv2::XmpKey("Xmp.dc.subject"), v1.get());
3675 g_list_free_full(tags, g_free);
3676 }
3677
3678 if (metadata->flags & DT_META_HIERARCHICAL_TAG)
3679 {
3680 std::unique_ptr<Exiv2::Value> v2(Exiv2::Value::create(Exiv2::xmpBag));
3681 GList *hierarchical = dt_tag_get_hierarchical_export(imgid, metadata->flags);
3682 for(GList *hier = hierarchical; hier; hier = g_list_next(hier))
3683 {
3684 v2->read((char *)hier->data);
3685 }
3686 if(v2->count() > 0) xmpData.add(Exiv2::XmpKey("Xmp.lr.hierarchicalSubject"), v2.get());
3687 g_list_free_full(hierarchical, g_free);
3688 }
3689
3690 if (metadata->flags & DT_META_DT_HISTORY)
3691 {
3692 xmpData["Xmp.darktable.xmp_version"] = xmp_version;
3693 xmpData["Xmp.darktable.raw_params"] = raw_params;
3694 if(stars & DT_IMAGE_AUTO_PRESETS_APPLIED)
3695 xmpData["Xmp.darktable.auto_presets_applied"] = 1;
3696 else
3697 xmpData["Xmp.darktable.auto_presets_applied"] = 0;
3698 dt_set_xmp_dt_history(xmpData, imgid, history_end);
3699
3700 // we need to read the iop-order list
3701 xmpData["Xmp.darktable.iop_order_version"] = iop_order_version;
3702 if(iop_order_list) xmpData["Xmp.darktable.iop_order_list"] = iop_order_list;
3703 }
3704
3705 sqlite3_finalize(stmt);
3706 g_free(iop_order_list);
3707 }
3708
3709 #if EXIV2_VERSION >= EXIV2_MAKE_VERSION(0,27,0)
3710 #define ERROR_CODE(a) (static_cast<Exiv2::ErrorCode>((a)))
3711 #else
3712 #define ERROR_CODE(a) (a)
3713 #endif
3714
dt_exif_xmp_read_string(const int imgid)3715 char *dt_exif_xmp_read_string(const int imgid)
3716 {
3717 try
3718 {
3719 char input_filename[PATH_MAX] = { 0 };
3720 gboolean from_cache = FALSE;
3721 dt_image_full_path(imgid, input_filename, sizeof(input_filename), &from_cache);
3722
3723 // first take over the data from the source image
3724 Exiv2::XmpData xmpData;
3725 if(g_file_test(input_filename, G_FILE_TEST_EXISTS))
3726 {
3727 std::string xmpPacket;
3728
3729 Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
3730 xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
3731 Exiv2::XmpParser::decode(xmpData, xmpPacket);
3732 // because XmpSeq or XmpBag are added to the list, we first have
3733 // to remove these so that we don't end up with a string of duplicates
3734 dt_remove_known_keys(xmpData);
3735 }
3736
3737 // now add whatever we have in the sidecar XMP. this overwrites stuff from the source image
3738 dt_image_path_append_version(imgid, input_filename, sizeof(input_filename));
3739 g_strlcat(input_filename, ".xmp", sizeof(input_filename));
3740 if(g_file_test(input_filename, G_FILE_TEST_EXISTS))
3741 {
3742 Exiv2::XmpData sidecarXmpData;
3743 std::string xmpPacket;
3744
3745 Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
3746 xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
3747 Exiv2::XmpParser::decode(sidecarXmpData, xmpPacket);
3748
3749 for(Exiv2::XmpData::const_iterator it = sidecarXmpData.begin(); it != sidecarXmpData.end(); ++it)
3750 xmpData.add(*it);
3751 }
3752
3753 dt_remove_known_keys(xmpData); // is this needed?
3754
3755 // last but not least attach what we have in DB to the XMP. in theory that should be
3756 // the same as what we just copied over from the sidecar file, but you never know ...
3757 _exif_xmp_read_data(xmpData, imgid);
3758
3759 // serialize the xmp data and output the xmp packet
3760 std::string xmpPacket;
3761 if(Exiv2::XmpParser::encode(xmpPacket, xmpData,
3762 Exiv2::XmpParser::useCompactFormat | Exiv2::XmpParser::omitPacketWrapper) != 0)
3763 {
3764 throw Exiv2::Error(ERROR_CODE(1), "[xmp_write] failed to serialize xmp data");
3765 }
3766 return g_strdup(xmpPacket.c_str());
3767 }
3768 catch(Exiv2::AnyError &e)
3769 {
3770 std::cerr << "[xmp_read_blob] caught exiv2 exception '" << e << "'\n";
3771 return NULL;
3772 }
3773 }
3774
dt_remove_xmp_key(Exiv2::XmpData & xmp,const char * key)3775 static void dt_remove_xmp_key(Exiv2::XmpData &xmp, const char *key)
3776 {
3777 try
3778 {
3779 Exiv2::XmpData::iterator pos = xmp.findKey(Exiv2::XmpKey(key));
3780 if (pos != xmp.end())
3781 xmp.erase(pos);
3782 }
3783 catch(Exiv2::AnyError &e)
3784 {
3785 }
3786 }
3787
_remove_xmp_keys(Exiv2::XmpData & xmpData,const char * key)3788 static void _remove_xmp_keys(Exiv2::XmpData &xmpData, const char *key)
3789 {
3790 try
3791 {
3792 const std::string needle = key;
3793 for(Exiv2::XmpData::iterator i = xmpData.begin(); i != xmpData.end();)
3794 {
3795 if(i->key().compare(0, needle.length(), needle) == 0)
3796 i = xmpData.erase(i);
3797 else
3798 ++i;
3799 }
3800 }
3801 catch(Exiv2::AnyError &e)
3802 {
3803 }
3804 }
3805
dt_remove_exif_key(Exiv2::ExifData & exif,const char * key)3806 static void dt_remove_exif_key(Exiv2::ExifData &exif, const char *key)
3807 {
3808 try
3809 {
3810 Exiv2::ExifData::iterator pos = exif.findKey(Exiv2::ExifKey(key));
3811 if (pos != exif.end())
3812 exif.erase(pos);
3813 }
3814 catch(Exiv2::AnyError &e)
3815 {
3816 }
3817 }
3818
dt_exif_xmp_attach_export(const int imgid,const char * filename,void * metadata)3819 int dt_exif_xmp_attach_export(const int imgid, const char *filename, void *metadata)
3820 {
3821 dt_export_metadata_t *m = (dt_export_metadata_t *)metadata;
3822 try
3823 {
3824 char input_filename[PATH_MAX] = { 0 };
3825 gboolean from_cache = TRUE;
3826 dt_image_full_path(imgid, input_filename, sizeof(input_filename), &from_cache);
3827
3828 std::unique_ptr<Exiv2::Image> img(Exiv2::ImageFactory::open(WIDEN(filename)));
3829 // unfortunately it seems we have to read the metadata, to not erase the exif (which we just wrote).
3830 // will make export slightly slower, oh well.
3831 // img->clearXmpPacket();
3832 read_metadata_threadsafe(img);
3833
3834 try
3835 {
3836 // initialize XMP and IPTC data with the one from the original file
3837 std::unique_ptr<Exiv2::Image> input_image(Exiv2::ImageFactory::open(WIDEN(input_filename)));
3838 if(input_image.get() != 0)
3839 {
3840 read_metadata_threadsafe(input_image);
3841 img->setIptcData(input_image->iptcData());
3842 img->setXmpData(input_image->xmpData());
3843 }
3844 }
3845 catch(Exiv2::AnyError &e)
3846 {
3847 std::cerr << "[xmp_attach] " << input_filename << ": caught exiv2 exception '" << e << "'\n";
3848 }
3849
3850 Exiv2::XmpData &xmpData = img->xmpData();
3851
3852 // now add whatever we have in the sidecar XMP. this overwrites stuff from the source image
3853 dt_image_path_append_version(imgid, input_filename, sizeof(input_filename));
3854 g_strlcat(input_filename, ".xmp", sizeof(input_filename));
3855 if(g_file_test(input_filename, G_FILE_TEST_EXISTS))
3856 {
3857 Exiv2::XmpData sidecarXmpData;
3858 std::string xmpPacket;
3859
3860 Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
3861 xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
3862 Exiv2::XmpParser::decode(sidecarXmpData, xmpPacket);
3863
3864 for(Exiv2::XmpData::const_iterator it = sidecarXmpData.begin(); it != sidecarXmpData.end(); ++it)
3865 xmpData.add(*it);
3866 }
3867
3868 dt_remove_known_keys(xmpData); // is this needed?
3869
3870 {
3871 // We also want to make sure to not have some tags that might
3872 // have come in from XMP files created by digikam or similar
3873 static const char *keys[] = {
3874 "Xmp.tiff.Orientation"
3875 };
3876 static const guint n_keys = G_N_ELEMENTS(keys);
3877 dt_remove_xmp_keys(xmpData, keys, n_keys);
3878 }
3879
3880 // last but not least attach what we have in DB to the XMP. in theory that should be
3881 // the same as what we just copied over from the sidecar file, but you never know ...
3882 // make sure to remove all geotags if necessary
3883 if(m)
3884 {
3885 Exiv2::ExifData exifOldData;
3886 Exiv2::ExifData &exifData = img->exifData();
3887 if(!(m->flags & DT_META_EXIF))
3888 {
3889 for(Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifData.end() ; ++i)
3890 {
3891 exifOldData[i->key()] = i->value();
3892 }
3893 img->clearExifData();
3894 }
3895
3896 _exif_xmp_read_data_export(xmpData, imgid, m);
3897
3898 Exiv2::IptcData &iptcData = img->iptcData();
3899
3900 if(!(m->flags & DT_META_GEOTAG))
3901 dt_remove_exif_geotag(exifData);
3902 // calculated metadata
3903 dt_variables_params_t *params;
3904 dt_variables_params_init(¶ms);
3905 params->filename = input_filename;
3906 params->jobcode = "export";
3907 params->sequence = 0;
3908 params->imgid = imgid;
3909
3910 dt_variables_set_tags_flags(params, m->flags);
3911 for (GList *tags = m->list; tags; tags = g_list_next(tags))
3912 {
3913 gchar *tagname = (gchar *)tags->data;
3914 tags = g_list_next(tags);
3915 if (!tags) break;
3916 gchar *formula = (gchar *)tags->data;
3917 if (formula[0])
3918 {
3919 if(!(m->flags & DT_META_EXIF) && (formula[0] == '=') && g_str_has_prefix(tagname, "Exif."))
3920 {
3921 // remove this specific exif
3922 Exiv2::ExifData::const_iterator pos;
3923 if(dt_exif_read_exif_tag(exifOldData, &pos, tagname))
3924 {
3925 exifData[tagname] = pos->value();
3926 }
3927 }
3928 else
3929 {
3930 gchar *result = dt_variables_expand(params, formula, FALSE);
3931 if(result && result[0])
3932 {
3933 if(g_str_has_prefix(tagname, "Xmp."))
3934 {
3935 const char *type = _exif_get_exiv2_tag_type(tagname);
3936 // if xmpBag or xmpSeq, split the list when necessary
3937 // else provide the string as is (can be a list of strings)
3938 if(!g_strcmp0(type, "XmpBag") || !g_strcmp0(type, "XmpSeq"))
3939 {
3940 char *tuple = g_strrstr(result, ",");
3941 while(tuple)
3942 {
3943 tuple[0] = '\0';
3944 tuple++;
3945 xmpData[tagname] = tuple;
3946 tuple = g_strrstr(result, ",");
3947 }
3948 }
3949 xmpData[tagname] = result;
3950 }
3951 else if(g_str_has_prefix(tagname, "Iptc."))
3952 {
3953 const char *type = _exif_get_exiv2_tag_type(tagname);
3954 if(!g_strcmp0(type, "String-R"))
3955 {
3956 // convert the input list (separator ", ") into different tags
3957 // FIXME if an element of the list contains a ", " it is not correctly expeorted
3958 Exiv2::IptcKey key(tagname);
3959 Exiv2::Iptcdatum id(key);
3960 gchar **values = g_strsplit(result, ", ", 0);
3961 if(values)
3962 {
3963 gchar **entry = values;
3964 while (*entry)
3965 {
3966 char *e = g_strstrip(*entry);
3967 if(*e)
3968 {
3969 id.setValue(e);
3970 iptcData.add(id);
3971 }
3972 entry++;
3973 }
3974 }
3975 g_strfreev(values);
3976 }
3977 else iptcData[tagname] = result;
3978 }
3979 else if(g_str_has_prefix(tagname, "Exif."))
3980 exifData[tagname] = result;
3981 }
3982 g_free(result);
3983 }
3984 }
3985 else
3986 {
3987 if (g_str_has_prefix(tagname, "Xmp."))
3988 dt_remove_xmp_key(xmpData, tagname);
3989 else if (g_str_has_prefix(tagname, "Exif."))
3990 dt_remove_exif_key(exifData, tagname);
3991 }
3992 }
3993 dt_variables_params_destroy(params);
3994 }
3995
3996 try
3997 {
3998 img->writeMetadata();
3999 }
4000 catch(Exiv2::AnyError &e)
4001 {
4002 #if EXIV2_VERSION >= EXIV2_MAKE_VERSION(0,27,0)
4003 if(e.code() == Exiv2::kerTooLargeJpegSegment)
4004 #else
4005 if(e.code() == 37)
4006 #endif
4007 {
4008 _remove_xmp_keys(xmpData, "Xmp.darktable.history");
4009 _remove_xmp_keys(xmpData, "Xmp.darktable.masks_history");
4010 _remove_xmp_keys(xmpData, "Xmp.darktable.auto_presets_applied");
4011 _remove_xmp_keys(xmpData, "Xmp.darktable.iop_order");
4012 try
4013 {
4014 img->writeMetadata();
4015 }
4016 catch(Exiv2::AnyError &e2)
4017 {
4018 std::cerr << "[dt_exif_xmp_attach_export] without history " << filename << ": caught exiv2 exception '" << e2 << "'\n";
4019 return -1;
4020 }
4021 }
4022 else
4023 throw;
4024 }
4025 return 0;
4026 }
4027 catch(Exiv2::AnyError &e)
4028 {
4029 std::cerr << "[dt_exif_xmp_attach_export] " << filename << ": caught exiv2 exception '" << e << "'\n";
4030 return -1;
4031 }
4032 }
4033
4034 // write xmp sidecar file:
dt_exif_xmp_write(const int imgid,const char * filename)4035 int dt_exif_xmp_write(const int imgid, const char *filename)
4036 {
4037 // refuse to write sidecar for non-existent image:
4038 char imgfname[PATH_MAX] = { 0 };
4039 gboolean from_cache = TRUE;
4040
4041 dt_image_full_path(imgid, imgfname, sizeof(imgfname), &from_cache);
4042 if(!g_file_test(imgfname, G_FILE_TEST_IS_REGULAR)) return 1;
4043
4044 try
4045 {
4046 Exiv2::XmpData xmpData;
4047 std::string xmpPacket;
4048 char *checksum_old = NULL;
4049 if(g_file_test(filename, G_FILE_TEST_EXISTS))
4050 {
4051 // we want to avoid writing the sidecar file if it didn't change to avoid issues when using the same images
4052 // from different computers. sample use case: images on NAS, several computers using them NOT AT THE SAME TIME and
4053 // the xmp crawler is used to find changed sidecars.
4054 errno = 0;
4055 size_t end;
4056 unsigned char *content = (unsigned char*)dt_read_file(filename, &end);
4057 if(content)
4058 {
4059 checksum_old = g_compute_checksum_for_data(G_CHECKSUM_MD5, content, end);
4060 free(content);
4061 }
4062 else
4063 {
4064 fprintf(stderr, "cannot read xmp file '%s': '%s'\n", filename, strerror(errno));
4065 dt_control_log(_("cannot read xmp file '%s': '%s'"), filename, strerror(errno));
4066 }
4067
4068 Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(filename));
4069 xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
4070 Exiv2::XmpParser::decode(xmpData, xmpPacket);
4071 // because XmpSeq or XmpBag are added to the list, we first have
4072 // to remove these so that we don't end up with a string of duplicates
4073 dt_remove_known_keys(xmpData);
4074 }
4075
4076 // initialize xmp data:
4077 _exif_xmp_read_data(xmpData, imgid);
4078
4079 // serialize the xmp data and output the xmp packet
4080 if(Exiv2::XmpParser::encode(xmpPacket, xmpData,
4081 Exiv2::XmpParser::useCompactFormat | Exiv2::XmpParser::omitPacketWrapper) != 0)
4082 {
4083 throw Exiv2::Error(ERROR_CODE(1), "[xmp_write] failed to serialize xmp data");
4084 }
4085
4086 // hash the new data and compare it to the old hash (if applicable)
4087 const char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
4088 gboolean write_sidecar = TRUE;
4089 if(checksum_old)
4090 {
4091 GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
4092 if(checksum)
4093 {
4094 g_checksum_update(checksum, (unsigned char*)xml_header, -1);
4095 g_checksum_update(checksum, (unsigned char*)xmpPacket.c_str(), -1);
4096 const char *checksum_new = g_checksum_get_string(checksum);
4097 write_sidecar = g_strcmp0(checksum_old, checksum_new) != 0;
4098 g_checksum_free(checksum);
4099 }
4100 g_free(checksum_old);
4101 }
4102
4103 if(write_sidecar)
4104 {
4105 // using std::ofstream isn't possible here -- on Windows it doesn't support Unicode filenames with mingw
4106 errno = 0;
4107 FILE *fout = g_fopen(filename, "wb");
4108 if(fout)
4109 {
4110 fprintf(fout, "%s", xml_header);
4111 fprintf(fout, "%s", xmpPacket.c_str());
4112 fclose(fout);
4113 }
4114 else
4115 {
4116 fprintf(stderr, "cannot write xmp file '%s': '%s'\n", filename, strerror(errno));
4117 dt_control_log(_("cannot write xmp file '%s': '%s'"), filename, strerror(errno));
4118 }
4119
4120 }
4121
4122 return 0;
4123 }
4124 catch(Exiv2::AnyError &e)
4125 {
4126 std::cerr << "[dt_exif_xmp_write] " << filename << ": caught exiv2 exception '" << e << "'\n";
4127 return -1;
4128 }
4129 }
4130
dt_exif_get_color_space(const uint8_t * data,size_t size)4131 dt_colorspaces_color_profile_type_t dt_exif_get_color_space(const uint8_t *data, size_t size)
4132 {
4133 try
4134 {
4135 Exiv2::ExifData::const_iterator pos;
4136 Exiv2::ExifData exifData;
4137 Exiv2::ExifParser::decode(exifData, data, size);
4138
4139 // 0x01 -> sRGB
4140 // 0x02 -> AdobeRGB
4141 // 0xffff -> Uncalibrated
4142 // + Exif.Iop.InteroperabilityIndex of 'R03' -> AdobeRGB
4143 // + Exif.Iop.InteroperabilityIndex of 'R98' -> sRGB
4144 if((pos = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ColorSpace"))) != exifData.end() && pos->size())
4145 {
4146 int colorspace = pos->toLong();
4147 if(colorspace == 0x01)
4148 return DT_COLORSPACE_SRGB;
4149 else if(colorspace == 0x02)
4150 return DT_COLORSPACE_ADOBERGB;
4151 else if(colorspace == 0xffff)
4152 {
4153 if((pos = exifData.findKey(Exiv2::ExifKey("Exif.Iop.InteroperabilityIndex"))) != exifData.end()
4154 && pos->size())
4155 {
4156 std::string interop_index = pos->toString();
4157 if(interop_index == "R03")
4158 return DT_COLORSPACE_ADOBERGB;
4159 else if(interop_index == "R98")
4160 return DT_COLORSPACE_SRGB;
4161 }
4162 }
4163 }
4164
4165 return DT_COLORSPACE_DISPLAY; // nothing embedded
4166 }
4167 catch(Exiv2::AnyError &e)
4168 {
4169 std::string s(e.what());
4170 std::cerr << "[exiv2 dt_exif_get_color_space] " << s << std::endl;
4171 return DT_COLORSPACE_DISPLAY;
4172 }
4173 }
4174
dt_exif_get_datetime_taken(const uint8_t * data,size_t size,time_t * datetime_taken)4175 gboolean dt_exif_get_datetime_taken(const uint8_t *data, size_t size, time_t *datetime_taken)
4176 {
4177 try
4178 {
4179 Exiv2::ExifData::const_iterator pos;
4180 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(data, size));
4181 read_metadata_threadsafe(image);
4182 Exiv2::ExifData &exifData = image->exifData();
4183
4184 char exif_datetime_taken[DT_DATETIME_LENGTH];
4185 _find_datetime_taken(exifData, pos, exif_datetime_taken);
4186
4187 if(*exif_datetime_taken)
4188 {
4189 struct tm exif_tm= {0};
4190 if(sscanf(exif_datetime_taken,"%d:%d:%d %d:%d:%d",
4191 &exif_tm.tm_year,
4192 &exif_tm.tm_mon,
4193 &exif_tm.tm_mday,
4194 &exif_tm.tm_hour,
4195 &exif_tm.tm_min,
4196 &exif_tm.tm_sec) == 6)
4197 {
4198 exif_tm.tm_year -= 1900;
4199 exif_tm.tm_mon--;
4200 exif_tm.tm_isdst = -1; // no daylight saving time
4201 *datetime_taken = mktime(&exif_tm);
4202 return TRUE;
4203 }
4204 }
4205
4206 return FALSE;
4207 }
4208 catch(Exiv2::AnyError &e)
4209 {
4210 std::string s(e.what());
4211 std::cerr << "[exiv2 dt_exif_get_datetime_taken] " << s << std::endl;
4212 return FALSE;
4213 }
4214 }
4215
dt_exif_log_handler(int log_level,const char * message)4216 static void dt_exif_log_handler(int log_level, const char *message)
4217 {
4218 if(log_level >= Exiv2::LogMsg::level())
4219 {
4220 // We don't seem to need \n in the format string as exiv2 includes it
4221 // in the messages themselves
4222 dt_print(DT_DEBUG_CAMERA_SUPPORT, "[exiv2] %s", message);
4223 }
4224 }
4225
dt_exif_init()4226 void dt_exif_init()
4227 {
4228 // preface the exiv2 messages with "[exiv2] "
4229 Exiv2::LogMsg::setHandler(&dt_exif_log_handler);
4230
4231 #ifdef HAVE_LIBEXIV2_WITH_ISOBMFF
4232 Exiv2::enableBMFF();
4233 #endif
4234
4235 Exiv2::XmpParser::initialize();
4236 // this has to stay with the old url (namespace already propagated outside dt)
4237 Exiv2::XmpProperties::registerNs("http://darktable.sf.net/", "darktable");
4238 // check is Exiv2 version already knows these prefixes
4239 try
4240 {
4241 Exiv2::XmpProperties::propertyList("lr");
4242 }
4243 catch(Exiv2::AnyError &e)
4244 {
4245 // if lightroom is not known register it
4246 Exiv2::XmpProperties::registerNs("http://ns.adobe.com/lightroom/1.0/", "lr");
4247 }
4248 try
4249 {
4250 Exiv2::XmpProperties::propertyList("exifEX");
4251 }
4252 catch(Exiv2::AnyError &e)
4253 {
4254 // if exifEX is not known register it
4255 Exiv2::XmpProperties::registerNs("http://cipa.jp/exif/1.0/", "exifEX");
4256 }
4257 }
4258
dt_exif_cleanup()4259 void dt_exif_cleanup()
4260 {
4261 Exiv2::XmpParser::terminate();
4262 }
4263
4264 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
4265 // vim: shiftwidth=2 expandtab tabstop=2 cindent
4266 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
4267