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(&params);
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                                                &current_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                                                          &current_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                                                    &current_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                                                            &current_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(), &current_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(), &current_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(&params);
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