Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
exif.cc
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2014, 2016 johannes hanika.
4 Copyright (C) 2010-2012 Henrik Andersson.
5 Copyright (C) 2010, 2012-2015 Pascal de Bruijn.
6 Copyright (C) 2010-2018 Tobias Ellinghaus.
7 Copyright (C) 2011-2012, 2018 Edouard Gomez.
8 Copyright (C) 2011 Jochen Schroeder.
9 Copyright (C) 2011 Johanes Schneider.
10 Copyright (C) 2011-2012 Jérémy Rosen.
11 Copyright (C) 2011 Kanstantsin Shautsou.
12 Copyright (C) 2011 Robert Bieber.
13 Copyright (C) 2011, 2013 Simon Spannagel.
14 Copyright (C) 2011 Uli Scholler.
15 Copyright (C) 2012-2013, 2020 Aldric Renaudin.
16 Copyright (C) 2012 Alexander Clausen.
17 Copyright (C) 2012 James C. McPherson.
18 Copyright (C) 2012-2013 José Carlos García Sogo.
19 Copyright (C) 2012 Richard Wonka.
20 Copyright (C) 2012 Sergey Pavlov.
21 Copyright (C) 2012-2014, 2016 Ulrich Pegelow.
22 Copyright (C) 2012 Wolfgang Kühnel.
23 Copyright (C) 2013 Dennis Gnad.
24 Copyright (C) 2013 Jacek Naglak.
25 Copyright (C) 2013-2015, 2018-2022 Pascal Obry.
26 Copyright (C) 2013-2017 Roman Lebedev.
27 Copyright (C) 2014-2015 Jan Niklas Fingerle.
28 Copyright (C) 2014 Michael Neumann.
29 Copyright (C) 2014-2016 Pedro Côrte-Real.
30 Copyright (C) 2015 Jake Probst.
31 Copyright (C) 2015, 2018 Marcel Müller.
32 Copyright (C) 2015 Tom Vijlbrief.
33 Copyright (C) 2015 Torsten Bronger.
34 Copyright (C) 2016 Matthieu Volat.
35 Copyright (C) 2017, 2020 David-Tillmann Schaefer.
36 Copyright (C) 2017, 2019, 2021 luzpaz.
37 Copyright (C) 2018-2019 Andreas Schneider.
38 Copyright (C) 2018-2019 Edgardo Hoszowski.
39 Copyright (C) 2018 Fabian Wenzel.
40 Copyright (C) 2019 codingdave.
41 Copyright (C) 2019-2021 Hanno Schwalm.
42 Copyright (C) 2019-2022 Philippe Weyland.
43 Copyright (C) 2020 Chris Elston.
44 Copyright (C) 2020-2021 Hubert Kowalski.
45 Copyright (C) 2020 JP Verrue.
46 Copyright (C) 2020 Matt Maguire.
47 Copyright (C) 2020-2022 Miloš Komarčević.
48 Copyright (C) 2020-2021 Ralf Brown.
49 Copyright (C) 2021, 2023, 2025-2026 Aurélien PIERRE.
50 Copyright (C) 2021 Daniel Vogelbacher.
51 Copyright (C) 2021 Victor Forsiuk.
52 Copyright (C) 2022 gi-man.
53 Copyright (C) 2022 Martin Bařinka.
54 Copyright (C) 2022 paolodepetrillo.
55 Copyright (C) 2023, 2025 Alynx Zhou.
56 Copyright (C) 2023 Ricky Moon.
57 Copyright (C) 2025-2026 Guillaume Stutin.
58
59 darktable is free software: you can redistribute it and/or modify
60 it under the terms of the GNU General Public License as published by
61 the Free Software Foundation, either version 3 of the License, or
62 (at your option) any later version.
63
64 darktable is distributed in the hope that it will be useful,
65 but WITHOUT ANY WARRANTY; without even the implied warranty of
66 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67 GNU General Public License for more details.
68
69 You should have received a copy of the GNU General Public License
70 along with darktable. If not, see <http://www.gnu.org/licenses/>.
71 */
72
73#define __STDC_FORMAT_MACROS
74
84#ifdef HAVE_CONFIG_H
85#include "config.h" // conditional-ok: generated only when the build system defines HAVE_CONFIG_H
86#endif
87
88#include <glib.h>
89#include <sys/stat.h>
90#include <time.h>
91#include <zlib.h>
92
93#include <cmath>
94#include <cstdlib>
95#include <cstring>
96#include <iostream>
97#include <string>
98
99#include <exiv2/exiv2.hpp>
100
101#include "metadata/exif.h"
103
104#include "common/conf.h"
105#include "common/datetime.h"
106#include "common/dng_opcode.h"
107#include "common/logging.h"
108#include "common/utility.h"
110#include "math/math.h"
111#include "metadata/colorlabels.h"
112#include "metadata/metadata.h"
113#include "metadata/notify.h"
114#include "metadata/tags.h"
115#include "system/macros.h"
116#include "system/mem_alloc.h"
117
118using namespace std;
119
120#if EXIV2_TEST_VERSION(0,28,0)
121#define AnyError Error
122#define toLong toInt64
123#endif
124
125// persistent list of exiv2 tags. set up in dt_init()
126static GList *exiv2_taglist = NULL;
127
128#if defined(_WIN32) && defined(EXV_UNICODE_PATH)
129std::wstring dt_exiv2_widen_path(const char *utf8_path)
130{
131 if(IS_NULL_PTR(utf8_path)) return std::wstring();
132
133 glong utf16_length = 0;
134 gunichar2 *utf16_path = g_utf8_to_utf16(utf8_path, -1, NULL, &utf16_length, NULL);
135
136 if(IS_NULL_PTR(utf16_path))
137 {
139 "[exiv2] path is not valid UTF-8, cannot convert it for Windows: `%s'\n", utf8_path);
140 return std::wstring();
141 }
142
143 // gunichar2 and wchar_t are both 16 bits wide on Windows, and both hold UTF-16 here.
144 std::wstring wide_path(reinterpret_cast<const wchar_t *>(utf16_path), (size_t)utf16_length);
145 dt_free(utf16_path);
146 return wide_path;
147}
148#endif
149
150static const char *_get_exiv2_type(const int type)
151{
152 switch(type)
153 {
154 case 1:
155 return "Byte";
156 case 2:
157 return "Ascii";
158 case 3:
159 return "Short";
160 case 4:
161 return "Long";
162 case 5:
163 return "Rational"; // two LONGs: numerator and denumerator of a fraction
164 case 6:
165 return "SByte";
166 case 7:
167 return "Undefined";
168 case 8:
169 return "SShort";
170 case 9:
171 return "SLong";
172 case 10:
173 return "SRational"; // two SLONGs: numerator and denumerator of a fraction.
174 case 11:
175 return "Float"; // single precision (4-byte) IEEE format
176 case 12:
177 return "Double"; // double precision (8-byte) IEEE format.
178 case 13:
179 return "Ifd"; // 32-bit (4-byte) unsigned integer
180 case 16:
181 return "LLong"; // 64-bit (8-byte) unsigned integer
182 case 17:
183 return "LLong"; // 64-bit (8-byte) signed integer
184 case 18:
185 return "Ifd8"; // 64-bit (8-byte) unsigned integer
186 case 0x10000:
187 return "String";
188 case 0x10001:
189 return "Date";
190 case 0x10002:
191 return "Time";
192 case 0x10003:
193 return "Comment";
194 case 0x10004:
195 return "Directory";
196 case 0x10005:
197 return "XmpText";
198 case 0x10006:
199 return "XmpAlt";
200 case 0x10007:
201 return "XmpBag";
202 case 0x10008:
203 return "XmpSeq";
204 case 0x10009:
205 return "LangAlt";
206 case 0x1fffe:
207 return "Invalid";
208 case 0x1ffff:
209 return "LastType";
210 default:
211 return "Invalid";
212 }
213}
214
215static void _get_xmp_tags(const char *prefix, GList **taglist)
216{
217 const Exiv2::XmpPropertyInfo *pl = Exiv2::XmpProperties::propertyList(prefix);
218 if(pl)
219 {
220 for (int i = 0; pl[i].name_ != 0; ++i)
221 {
222 char *tag = dt_util_dstrcat(NULL, "Xmp.%s.%s,%s", prefix, pl[i].name_, _get_exiv2_type(pl[i].typeId_));
223 *taglist = g_list_prepend(*taglist, tag);
224 }
225 }
226}
227
229{
230 switch(illu)
231 {
233 case DT_LS_Tungsten:
234 return 2850;
236 return 3200;
238 return 4871;
240 return 6774;
241 case DT_LS_D50:
242 return 5000;
243 case DT_LS_D55:
244 case DT_LS_Daylight:
246 case DT_LS_Flash:
247 return 5500;
248 case DT_LS_D65:
250 return 6500;
251 case DT_LS_D75:
252 case DT_LS_Shade:
253 return 7500;
255 return 6430;
257 return 5000;
259 return 4150;
261 return 4230;
263 return 3450;
265 return 2940;
266 default:
267 return 0;
268 }
269}
270
272{
273 if(exiv2_taglist) return;
274
275 try
276 {
277 const Exiv2::GroupInfo *groupList = Exiv2::ExifTags::groupList();
278 if(groupList)
279 {
280 while(groupList->tagList_)
281 {
282 const std::string groupName(groupList->groupName_);
283 if(groupName.substr(0, 3) != "Sub" &&
284 groupName != "Image2" &&
285 groupName != "Image3" &&
286 groupName != "Thumbnail"
287 )
288 {
289 const Exiv2::TagInfo *tagInfo = groupList->tagList_();
290 while(tagInfo->tag_ != 0xFFFF)
291 {
292 char *tag = dt_util_dstrcat(NULL, "Exif.%s.%s,%s", groupList->groupName_, tagInfo->name_, _get_exiv2_type(tagInfo->typeId_));
293 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
294 tagInfo++;
295 }
296 }
297 groupList++;
298 }
299 }
300
301 const Exiv2::DataSet *iptcEnvelopeList = Exiv2::IptcDataSets::envelopeRecordList();
302 while(iptcEnvelopeList->number_ != 0xFFFF)
303 {
304 char *tag = dt_util_dstrcat(NULL, "Iptc.Envelope.%s,%s%s", iptcEnvelopeList->name_,
305 _get_exiv2_type(iptcEnvelopeList->type_),
306 iptcEnvelopeList->repeatable_ ? "-R" : "");
307 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
308 iptcEnvelopeList++;
309 }
310
311 const Exiv2::DataSet *iptcApplication2List = Exiv2::IptcDataSets::application2RecordList();
312 while(iptcApplication2List->number_ != 0xFFFF)
313 {
314 char *tag = dt_util_dstrcat(NULL, "Iptc.Application2.%s,%s%s", iptcApplication2List->name_,
315 _get_exiv2_type(iptcApplication2List->type_),
316 iptcApplication2List->repeatable_ ? "-R" : "");
317 exiv2_taglist = g_list_prepend(exiv2_taglist, tag);
318 iptcApplication2List++;
319 }
320
323 _get_xmp_tags("xmpRights", &exiv2_taglist);
324 _get_xmp_tags("xmpMM", &exiv2_taglist);
325 _get_xmp_tags("xmpBJ", &exiv2_taglist);
326 _get_xmp_tags("xmpTPg", &exiv2_taglist);
327 _get_xmp_tags("xmpDM", &exiv2_taglist);
329 _get_xmp_tags("photoshop", &exiv2_taglist);
333 _get_xmp_tags("exifEX", &exiv2_taglist);
336 _get_xmp_tags("iptcExt", &exiv2_taglist);
338 _get_xmp_tags("mwg-rs", &exiv2_taglist);
339 _get_xmp_tags("mwg-kw", &exiv2_taglist);
341 _get_xmp_tags("dcterms", &exiv2_taglist);
342 _get_xmp_tags("digiKam", &exiv2_taglist);
344 _get_xmp_tags("GPano", &exiv2_taglist);
348 _get_xmp_tags("MPReg", &exiv2_taglist);
349 _get_xmp_tags("acdsee", &exiv2_taglist);
350 _get_xmp_tags("mediapro", &exiv2_taglist);
351 _get_xmp_tags("expressionmedia", &exiv2_taglist);
352 _get_xmp_tags("MicrosoftPhoto", &exiv2_taglist);
353 }
354 catch (Exiv2::AnyError& e)
355 {
356 std::string s(e.what());
357 std::cerr << "[exiv2 taglist] " << s << std::endl;
358 }
359}
360
362{
363 if(!exiv2_taglist)
365 return exiv2_taglist;
366}
367
368static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos);
369
370// inspired by ufraw_exiv2.cc:
371
372static void dt_strlcpy_to_utf8(char *dest, size_t dest_max, Exiv2::ExifData::const_iterator &pos,
373 Exiv2::ExifData &exifData)
374{
375 std::string str = pos->print(&exifData);
376
377 char *s = g_locale_to_utf8(str.c_str(), str.length(), NULL, NULL, NULL);
378 if(!IS_NULL_PTR(s))
379 {
380 g_strlcpy(dest, s, dest_max);
381 dt_free(s);
382 }
383 else
384 {
385 g_strlcpy(dest, str.c_str(), dest_max);
386 }
387}
388
389void dt_remove_exif_keys(Exiv2::ExifData &exif, const char *keys[], unsigned int n_keys)
390{
391 for(unsigned int i = 0; i < n_keys; i++)
392 {
393 try
394 {
395 Exiv2::ExifData::iterator pos;
396 while((pos = exif.findKey(Exiv2::ExifKey(keys[i]))) != exif.end())
397 exif.erase(pos);
398 }
399 catch(const std::exception &e)
400 {
401 // the only exception we may get is "invalid" tag, which is not
402 // important enough to either stop the function, or even display
403 // a message (it's probably the tag is not implemented in the
404 // exiv2 version used)
405 }
406 }
407}
408
409static bool dt_exif_read_xmp_tag(Exiv2::XmpData &xmpData, Exiv2::XmpData::iterator *pos, string key)
410{
411 try
412 {
413 return (*pos = xmpData.findKey(Exiv2::XmpKey(key))) != xmpData.end() && (*pos)->size();
414 }
415 catch(const std::exception &e)
416 {
417 std::string s(e.what());
418 std::cerr << "[exiv2 read_xmp_tag] " << s << std::endl;
419 return false;
420 }
421}
422#define FIND_XMP_TAG(key) dt_exif_read_xmp_tag(xmpData, &pos, key)
423
424
425// FIXME: according to http://www.exiv2.org/doc/classExiv2_1_1Metadatum.html#63c2b87249ba96679c29e01218169124
426// there is no need to pass xmpData
427// version = -1 -> version ignored
428bool dt_exif_decode_xmp_data(dt_image_t *img, Exiv2::XmpData &xmpData, int version,
429 bool exif_read)
430{
431 // as this can be called several times during the image lifetime, clean up first
432 GList *imgs = NULL;
433 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img->id));
434 try
435 {
436 Exiv2::XmpData::iterator pos;
437
438 // older darktable version did not write this data correctly:
439 // the reasoning behind strdup'ing all the strings before passing it to sqlite3 is, that
440 // they are somehow corrupt after the call to sqlite3_prepare_v2() -- don't ask me
441 // why for they don't get passed to that function.
442 if(version == -1 || version > 0)
443 {
444 if(!exif_read) dt_metadata_clear(imgs, FALSE);
445 for(unsigned int i = 0; i < DT_METADATA_NUMBER; i++)
446 {
447 const gchar *key = dt_metadata_get_key(i);
448 if(FIND_XMP_TAG(key))
449 {
450 char *value = strdup(pos->toString().c_str());
451 char *adr = value;
452 // skip any lang="" or charset=xxx
453 while(!strncmp(value, "lang=", 5) || !strncmp(value, "charset=", 8))
454 {
455 while(*value != ' ' && *value) value++;
456 while(*value == ' ') value++;
457 }
459 dt_free(adr);
460 }
461 }
462 }
463
464 if(FIND_XMP_TAG("Xmp.xmp.Rating"))
465 {
466 const int stars = pos->toLong();
467 dt_image_set_xmp_rating(img, stars);
468 }
469 else
471
472 if(!exif_read) dt_colorlabels_remove_labels(img->id);
473 if(FIND_XMP_TAG("Xmp.xmp.Label"))
474 {
475 std::string label = pos->toString();
476 if(label == "Red") // Is it really called like that in XMP files?
478 else if(label == "Yellow") // Is it really called like that in XMP files?
480 else if(label == "Green")
482 else if(label == "Blue") // Is it really called like that in XMP files?
484 else if(label == "Purple") // Is it really called like that in XMP files?
486 }
487 // if Xmp.xmp.Label not managed from an external app use dt colors
488 else if(FIND_XMP_TAG("Xmp.darktable.colorlabels"))
489 {
490 // color labels
491 const int cnt = pos->count();
492 for(int i = 0; i < cnt; i++)
493 {
494 dt_colorlabels_set_label(img->id, pos->toLong(i));
495 }
496 }
497
498 if((dt_image_get_xmp_mode()) ||
499 dt_conf_get_bool("ui_last/import_last_tags_imported"))
500 {
501 GList *tags = NULL;
502 // preserve dt tags which are not saved in xmp file
503 if(!exif_read) dt_tag_set_tags(tags, imgs, TRUE, TRUE, FALSE);
504 if(FIND_XMP_TAG("Xmp.lr.hierarchicalSubject"))
505 _exif_import_tags(img, pos);
506 else if(FIND_XMP_TAG("Xmp.dc.subject"))
507 _exif_import_tags(img, pos);
508 }
509
510 /* read gps location */
511 if(FIND_XMP_TAG("Xmp.exif.GPSLatitude"))
512 {
513 img->geoloc.latitude = dt_util_gps_string_to_number(pos->toString().c_str());
514 }
515
516 if(FIND_XMP_TAG("Xmp.exif.GPSLongitude"))
517 {
518 img->geoloc.longitude = dt_util_gps_string_to_number(pos->toString().c_str());
519 }
520
521 if(FIND_XMP_TAG("Xmp.exif.GPSAltitude"))
522 {
523 Exiv2::XmpData::const_iterator ref = xmpData.findKey(Exiv2::XmpKey("Xmp.exif.GPSAltitudeRef"));
524 if(ref != xmpData.end() && ref->size())
525 {
526 std::string sign_str = ref->toString();
527 const char *sign = sign_str.c_str();
528 double elevation = 0.0;
529 if(dt_util_gps_elevation_to_number(pos->toRational(0).first, pos->toRational(0).second, sign[0], &elevation))
530 img->geoloc.elevation = elevation;
531 }
532 }
533
534 /* read lens type from Xmp.exifEX.LensModel */
535 if(FIND_XMP_TAG("Xmp.exifEX.LensModel"))
536 {
537 // lens model
538 char *lens = strdup(pos->toString().c_str());
539 char *adr = lens;
540 if(strncmp(lens, "lang=", 5) == 0)
541 {
542 lens = strchr(lens, ' ');
543 if(!IS_NULL_PTR(lens)) lens++;
544 }
545 // no need to do any Unicode<->locale conversion, the field is specified as ASCII
546 g_strlcpy(img->exif_lens, lens, sizeof(img->exif_lens));
547 dt_free(adr);
548 }
549
550 /* read timestamp from Xmp.exif.DateTimeOriginal */
551 if(FIND_XMP_TAG("Xmp.exif.DateTimeOriginal")
552 || FIND_XMP_TAG("Xmp.photoshop.DateCreated"))
553 {
554 char *datetime = strdup(pos->toString().c_str());
555 if(datetime[0] != '\0') dt_datetime_exif_to_img(img, datetime);
556 dt_free(datetime);
557 }
558
559 if(imgs)
560 {
561 g_list_free(imgs);
562 imgs = NULL;
563 }
564 imgs = NULL;
565 return true;
566 }
567 catch(const std::exception &e)
568 {
569 if(imgs)
570 {
571 g_list_free(imgs);
572 imgs = NULL;
573 }
574 imgs = NULL;
575 std::string s(e.what());
576 std::cerr << "[exiv2 dt_exif_decode_xmp_data] " << img->filename << ": " << s << std::endl;
577 return false;
578 }
579}
580
581static bool dt_exif_read_iptc_tag(Exiv2::IptcData &iptcData, Exiv2::IptcData::const_iterator *pos, string key)
582{
583 try
584 {
585 return (*pos = iptcData.findKey(Exiv2::IptcKey(key))) != iptcData.end() && (*pos)->size();
586 }
587 catch(const std::exception &e)
588 {
589 std::string s(e.what());
590 std::cerr << "[exiv2 read_iptc_tag] " << s << std::endl;
591 return false;
592 }
593}
594#define FIND_IPTC_TAG(key) dt_exif_read_iptc_tag(iptcData, &pos, key)
595
596
597// FIXME: according to http://www.exiv2.org/doc/classExiv2_1_1Metadatum.html#63c2b87249ba96679c29e01218169124
598// there is no need to pass iptcData
599static bool _exif_decode_iptc_data(dt_image_t *img, Exiv2::IptcData &iptcData)
600{
601 try
602 {
603 Exiv2::IptcData::const_iterator pos;
604 iptcData.sortByKey(); // this helps to quickly find all Iptc.Application2.Keywords
605
606 if((pos = iptcData.findKey(Exiv2::IptcKey("Iptc.Application2.Keywords"))) != iptcData.end())
607 {
608 while(pos != iptcData.end())
609 {
610 std::string key = pos->key();
611 if(g_strcmp0(key.c_str(), "Iptc.Application2.Keywords")) break;
612 std::string str = pos->print();
613 char *tag = dt_util_foo_to_utf8(str.c_str());
614 guint tagid = 0;
615 dt_tag_new(tag, &tagid);
616 dt_tag_attach(tagid, img->id, FALSE, FALSE);
617 dt_free(tag);
618 ++pos;
619 }
621 }
622 if(FIND_IPTC_TAG("Iptc.Application2.Caption"))
623 {
624 std::string str = pos->print(/*&iptcData*/);
625 dt_metadata_set_import(img->id, "Xmp.dc.description", str.c_str());
626 }
627 if(FIND_IPTC_TAG("Iptc.Application2.Copyright"))
628 {
629 std::string str = pos->print(/*&iptcData*/);
630 dt_metadata_set_import(img->id, "Xmp.dc.rights", str.c_str());
631 }
632 if(FIND_IPTC_TAG("Iptc.Application2.Byline"))
633 {
634 std::string str = pos->print(/*&iptcData*/);
635 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
636 }
637 else if(FIND_IPTC_TAG("Iptc.Application2.Writer"))
638 {
639 std::string str = pos->print(/*&iptcData*/);
640 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
641 }
642 else if(FIND_IPTC_TAG("Iptc.Application2.Contact"))
643 {
644 std::string str = pos->print(/*&iptcData*/);
645 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
646 }
647 if(FIND_IPTC_TAG("Iptc.Application2.DateCreated"))
648 {
649 // exiv2 already converts IPTC date and time into ISO 8601 format
650 GString *datetime = g_string_new(pos->toString().c_str());
651
652 datetime = g_string_append(datetime, "T");
653 if(FIND_IPTC_TAG("Iptc.Application2.TimeCreated"))
654 {
655 gchar *time = g_strdup(pos->toString().c_str());
656 datetime = g_string_append(datetime, time);
657 dt_free(time);
658 }
659 else
660 datetime = g_string_append(datetime, "00:00:00");
661
662 if(datetime->str[0] != '\0') dt_datetime_exif_to_img(img, datetime->str);
663 g_string_free(datetime, TRUE);
664 }
665
666 return true;
667 }
668 catch(const std::exception &e)
669 {
670 std::string s(e.what());
671 std::cerr << "[exiv2 _exif_decode_iptc_data] " << img->filename << ": " << s << std::endl;
672 return false;
673 }
674}
675
676bool dt_exif_read_exif_tag(Exiv2::ExifData &exifData,
677 Exiv2::ExifData::const_iterator *pos, string key)
678{
679 try
680 {
681 return (*pos = exifData.findKey(Exiv2::ExifKey(key)))
682 != exifData.end() && (*pos)->size();
683 }
684 catch(const std::exception &e)
685 {
686 std::string s(e.what());
687 std::cerr << "[exiv2 read_exif_tag] " << s << std::endl;
688 return false;
689 }
690}
691#define FIND_EXIF_TAG(key) dt_exif_read_exif_tag(exifData, &pos, key)
692
693// Two candidate copies of DefaultUserCrop are compared edge by edge with this absolute
694// tolerance: the same rectangle can be encoded as different rationals in different IFDs, so
695// bitwise equality would report a conflict where none exists.
696#define DT_IMAGE_USERCROP_EPSILON 1e-6f
697
710static dt_image_usercrop_status_t _read_usercrop_candidate(Exiv2::ExifData &exifData, const char *key,
711 dt_boundingbox_t crop)
712{
713 crop[0] = crop[1] = 0.f;
714 crop[2] = crop[3] = 1.f;
715
716 Exiv2::ExifData::const_iterator pos = exifData.findKey(Exiv2::ExifKey(key));
717 if(pos == exifData.end()) return DT_IMAGE_USERCROP_ABSENT;
718
719 if(pos->count() != 4 || !pos->size()) return DT_IMAGE_USERCROP_MALFORMED;
720
721 for(int i = 0; i < 4; i++)
722 {
723 crop[i] = pos->toFloat(i);
724 if(!std::isfinite(crop[i])) return DT_IMAGE_USERCROP_MALFORMED;
725 }
726
727 // 0 <= top < bottom <= 1 and 0 <= left < right <= 1
728 if(!(crop[0] >= 0.f && crop[0] < crop[2] && crop[2] <= 1.f)) return DT_IMAGE_USERCROP_MALFORMED;
729 if(!(crop[1] >= 0.f && crop[1] < crop[3] && crop[3] <= 1.f)) return DT_IMAGE_USERCROP_MALFORMED;
730
731 if(crop[0] == 0.f && crop[1] == 0.f && crop[2] == 1.f && crop[3] == 1.f)
733
735}
736
738{
739 for(int i = 0; i < 4; i++)
740 if(fabsf(a[i] - b[i]) > DT_IMAGE_USERCROP_EPSILON) return false;
741
742 return true;
743}
744
751static bool _check_usercrop(Exiv2::ExifData &exifData, dt_image_t *img)
752{
753 // Exif.SubImage1 holds the raw IFD of a DNG with an embedded preview; DNGs without one carry
754 // the raw image tags under Exif.Image instead. Both are documented compatibility candidates,
755 // neither is proof of which IFD the decoder actually selected -- so when both are present and
756 // disagree, refuse rather than silently pick one.
757 dt_boundingbox_t sub_image_crop, image_crop;
758 const dt_image_usercrop_status_t sub_image_status
759 = _read_usercrop_candidate(exifData, "Exif.SubImage1.0xc7b5", sub_image_crop);
760 const dt_image_usercrop_status_t image_status
761 = _read_usercrop_candidate(exifData, "Exif.Image.0xc7b5", image_crop);
762
764 const float *crop;
765
766 if(sub_image_status == DT_IMAGE_USERCROP_VALID && image_status == DT_IMAGE_USERCROP_VALID
767 && !_usercrop_candidates_agree(sub_image_crop, image_crop))
768 {
770 crop = NULL;
771 }
772 else if(sub_image_status != DT_IMAGE_USERCROP_ABSENT)
773 {
774 status = sub_image_status;
775 crop = sub_image_crop;
776 }
777 else
778 {
779 status = image_status;
780 crop = image_crop;
781 }
782
783 img->usercrop_status = status;
784 img->usercrop[0] = img->usercrop[1] = 0.f;
785 img->usercrop[2] = img->usercrop[3] = 1.f;
786
788 {
789 for(int i = 0; i < 4; i++) img->usercrop[i] = crop[i];
791 "[exif] image %d: DNG DefaultUserCrop (top, left, bottom, right) = (%f, %f, %f, %f)\n",
792 img->id, crop[0], crop[1], crop[2], crop[3]);
793 return TRUE;
794 }
795
796 // ABSENT and IDENTITY are the normal case for most files: stay silent about them.
799 "[exif] image %d: ignoring DNG DefaultUserCrop, the camera framing metadata is %s\n",
800 img->id, (status == DT_IMAGE_USERCROP_CONFLICT) ? "contradictory between IFDs" : "malformed");
801
802 return FALSE;
803}
804
805static gboolean _check_dng_opcodes(Exiv2::ExifData &exifData, dt_image_t *img)
806{
807 gboolean has_opcodes = FALSE;
808 Exiv2::ExifData::const_iterator pos = exifData.findKey(Exiv2::ExifKey("Exif.SubImage1.OpcodeList2"));
809 // DNGs without an embedded preview have the opcodes under Exif.Image instead of Exif.SubImage1
810 if(pos == exifData.end())
811 pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.OpcodeList2"));
812 if(pos != exifData.end())
813 {
814 g_autofree uint8_t *data = (uint8_t *)g_malloc(pos->size()); // NOSONAR
815 pos->copy(data, Exiv2::invalidByteOrder);
816 dt_dng_opcode_process_opcode_list_2(data, pos->size(), img);
817 has_opcodes = TRUE;
818 }
819 else
820 {
821 dt_vprint(DT_DEBUG_IMAGEIO, "DNG OpcodeList2 tag not found\n");
822 }
823 return has_opcodes;
824}
825
826static void _check_lens_correction_dng(Exiv2::ExifData &exifData, dt_image_t *img)
827{
828 Exiv2::ExifData::const_iterator pos = exifData.findKey(Exiv2::ExifKey("Exif.SubImage1.OpcodeList3"));
829 if(pos == exifData.end()) pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.OpcodeList3"));
830 if(pos != exifData.end())
831 {
832 g_autofree uint8_t *data = (uint8_t *)g_malloc(pos->size()); // NOSONAR
833 pos->copy(data, Exiv2::invalidByteOrder);
834 /* The blob's format is correction knowledge, so LensSerious parses it -- this file
835 * only lifts the bytes out of the tag. See lensserious_vendor.h. */
836 if(ls_vendor_parse_dng_opcodelist3(data, pos->size(), &img->exif_correction.u.dng) > 0)
837 img->exif_correction.type = LS_VENDOR_DNG;
838 }
839 else
840 {
841 dt_vprint(DT_DEBUG_IMAGEIO, "DNG OpcodeList3 tag not found\n");
842 }
843}
844
845static void _check_lens_correction_sony(Exiv2::ExifData &exifData, dt_image_t *img)
846{
847 Exiv2::ExifData::const_iterator posd;
848 Exiv2::ExifData::const_iterator posc;
849 Exiv2::ExifData::const_iterator posv;
850 if((dt_exif_read_exif_tag(exifData, &posd, "Exif.SubImage1.DistortionCorrParams")
851 && dt_exif_read_exif_tag(exifData, &posc, "Exif.SubImage1.ChromaticAberrationCorrParams")
852 && dt_exif_read_exif_tag(exifData, &posv, "Exif.SubImage1.VignettingCorrParams"))
853 || (dt_exif_read_exif_tag(exifData, &posd, "Exif.Image.0x7037")
854 && dt_exif_read_exif_tag(exifData, &posc, "Exif.Image.0x7035")
855 && dt_exif_read_exif_tag(exifData, &posv, "Exif.Image.0x7032")))
856 {
857 const int nc = posd->toLong(0);
858 if(nc <= 16 && 2 * nc == posc->toLong(0) && nc == posv->toLong(0)
859 && (int)posd->count() >= nc + 1
860 && (int)posc->count() >= 2 * nc + 1
861 && (int)posv->count() >= nc + 1)
862 {
863 img->exif_correction.u.sony.nc = nc;
864 for(int i = 0; i < nc; i++)
865 {
866 img->exif_correction.u.sony.distortion[i] = posd->toLong(i + 1);
867 img->exif_correction.u.sony.ca_r[i] = posc->toLong(i + 1);
868 img->exif_correction.u.sony.ca_b[i] = posc->toLong(nc + i + 1);
869 img->exif_correction.u.sony.vignetting[i] = posv->toLong(i + 1);
870 }
871 img->exif_correction.type = LS_VENDOR_SONY;
872 }
873 }
874}
875
876static bool _read_fuji_9coef(Exiv2::ExifData::const_iterator posd, Exiv2::ExifData::const_iterator posc,
877 Exiv2::ExifData::const_iterator posv, ls_vendor_fuji_t *f)
878{
879 f->nc = 9;
880 for(int i = 0; i < 9; i++)
881 {
882 const float kd = posd->toFloat(i + 1);
883 const float kc = posc->toFloat(i + 1);
884 const float kv = posv->toFloat(i + 1);
885 if(kd != kc || kd != kv) return false;
886 f->knots[i] = kd;
887 f->distortion[i] = posd->toFloat(i + 10);
888 f->ca_r[i] = posc->toFloat(i + 10);
889 f->ca_b[i] = posc->toFloat(i + 19);
890 f->vignetting[i] = posv->toFloat(i + 10);
891 }
892 return true;
893}
894
895static bool _read_fuji_11coef(Exiv2::ExifData::const_iterator posd, Exiv2::ExifData::const_iterator posc,
896 Exiv2::ExifData::const_iterator posv, ls_vendor_fuji_t *f)
897{
898 f->nc = 11;
899 for(int i = 0; i < 11; i++)
900 {
901 const float kd = posd->toFloat(i + 1);
902 const float kc = (i != 0) ? posc->toFloat(i) : 0.0f;
903 const float kv = posv->toFloat(i + 1);
904 if(kd != kc || kd != kv) return false;
905 f->knots[i] = kd;
906 f->distortion[i] = posd->toFloat(i + 12);
907 if(i == 0)
908 {
909 f->ca_r[i] = 0.0f;
910 f->ca_b[i] = 0.0f;
911 }
912 else
913 {
914 f->ca_r[i] = posc->toFloat(i + 10);
915 f->ca_b[i] = posc->toFloat(i + 20);
916 }
917 f->vignetting[i] = posv->toFloat(i + 12);
918 }
919 return true;
920}
921static void _check_lens_correction_fuji(Exiv2::ExifData &exifData, dt_image_t *img)
922{
923 Exiv2::ExifData::const_iterator posd;
924 Exiv2::ExifData::const_iterator posc;
925 Exiv2::ExifData::const_iterator posv;
926 Exiv2::ExifData::const_iterator posm;
927 if(!dt_exif_read_exif_tag(exifData, &posd, "Exif.Fujifilm.GeometricDistortionParams")
928 || !dt_exif_read_exif_tag(exifData, &posc, "Exif.Fujifilm.ChromaticAberrationParams")
929 || !dt_exif_read_exif_tag(exifData, &posv, "Exif.Fujifilm.VignettingParams"))
930 return;
931
932 if(posd->count() == 19 && posc->count() == 29 && posv->count() == 19)
933 {
934 if(!_read_fuji_9coef(posd, posc, posv, &img->exif_correction.u.fuji))
935 {
936 img->exif_correction.type = LS_VENDOR_NONE;
937 return;
938 }
939 img->exif_correction.type = LS_VENDOR_FUJI;
940 }
941 else if(posd->count() == 23 && posc->count() == 31 && posv->count() == 23)
942 {
943 if(!_read_fuji_11coef(posd, posc, posv, &img->exif_correction.u.fuji))
944 {
945 img->exif_correction.type = LS_VENDOR_NONE;
946 return;
947 }
948 img->exif_correction.type = LS_VENDOR_FUJI;
949 }
950 else
951 {
952 return;
953 }
954
955 if(dt_exif_read_exif_tag(exifData, &posm, "Exif.Fujifilm.CropMode")
956 && (posm->toLong() == 2 || posm->toLong() == 4))
957 img->exif_correction.u.fuji.cropf = 1.25f;
958 else
959 img->exif_correction.u.fuji.cropf = 1.0f;
960}
961
962static void _check_lens_correction_olympus(Exiv2::ExifData &exifData, dt_image_t *img)
963{
964 Exiv2::ExifData::const_iterator posip;
965
966 if(dt_exif_read_exif_tag(exifData, &posip, "Exif.OlympusIp.0x150a") && posip->count() == 4)
967 {
968 for(int i = 0; i < 4; i++)
969 {
970 const float kd = posip->toFloat(i);
971 img->exif_correction.u.olympus.dist[i] = kd;
972 if(kd != 0.0f && i < 3)
973 {
974 img->exif_correction.type = LS_VENDOR_OLYMPUS;
975 img->exif_correction.u.olympus.has_dist = TRUE;
976 }
977 }
978 }
979
980 if(dt_exif_read_exif_tag(exifData, &posip, "Exif.OlympusIp.0x150c") && posip->count() == 6)
981 {
982 for(int i = 0; i < 6; i++)
983 {
984 const float kc = posip->toFloat(i);
985 img->exif_correction.u.olympus.ca[i] = kc;
986 if(kc != 0.0f)
987 {
988 img->exif_correction.type = LS_VENDOR_OLYMPUS;
989 img->exif_correction.u.olympus.has_ca = TRUE;
990 }
991 }
992 }
993}
994
995static void _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_t *img)
996{
997 img->exif_correction.type = LS_VENDOR_NONE;
998 memset(&img->exif_correction, 0, sizeof(img->exif_correction));
999
1000 if(!Exiv2::testVersion(0, 27, 4)) return;
1001
1002 /* First match wins, and the order is a decision rather than an accident.
1003 *
1004 * These used to run unconditionally, so when two vendors' tags were both present the LAST
1005 * one to match silently won -- a priority nobody had chosen. It is reachable: a Sony raw
1006 * converted to DNG carries the converter's OpcodeList3 and the original maker notes side
1007 * by side.
1008 *
1009 * DNG goes first because in that file the opcodes are the authoritative description. The
1010 * converter may have cropped or rotated relative to the sensor the maker notes describe,
1011 * and the opcodes account for what the DNG actually contains; the maker notes describe a
1012 * frame that no longer exists. For a camera that shoots DNG natively there is nothing to
1013 * choose between anyway, since only the opcodes are there. */
1014 _check_lens_correction_dng(exifData, img);
1015 if(img->exif_correction.type == LS_VENDOR_NONE)
1016 _check_lens_correction_sony(exifData, img);
1017 if(img->exif_correction.type == LS_VENDOR_NONE)
1018 _check_lens_correction_fuji(exifData, img);
1019 if(img->exif_correction.type == LS_VENDOR_NONE)
1020 _check_lens_correction_olympus(exifData, img);
1021
1022 /* Says which maker answered, or that none did. Worth logging rather than inferring from
1023 * the absence of a correction: "this camera embeds nothing" and "we failed to read what
1024 * it embedded" look identical in the picture and completely different here. */
1025 static const char *const names[] = { "none", "Sony", "Fujifilm", "DNG opcodes", "Olympus" };
1026 const int t = (int)img->exif_correction.type;
1027 dt_vprint(DT_DEBUG_IMAGEIO, "[exif] embedded lens correction: %s\n",
1028 (t >= 0 && t < (int)(sizeof(names) / sizeof(*names))) ? names[t] : "unknown");
1029}
1030
1031void dt_exif_read_usercrop(dt_image_t *img, const char *filename)
1032{
1033 // Leave a definite answer even when the file cannot be read, so callers that use
1034 // DT_IMAGE_USERCROP_UNKNOWN as a "not looked at yet" marker do not retry on every request.
1036 img->usercrop[0] = img->usercrop[1] = 0.f;
1037 img->usercrop[2] = img->usercrop[3] = 1.f;
1038
1039 try
1040 {
1041 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
1042 if(!image.get()) return;
1043 image->readMetadata();
1044 Exiv2::ExifData &exifData = image->exifData();
1045 if(exifData.empty()) return;
1046 _check_usercrop(exifData, img);
1047 }
1048 catch(const std::exception &e)
1049 {
1050 std::string s(e.what());
1051 std::cerr << "[exiv2 dt_exif_read_usercrop] " << filename << ": " << s << std::endl;
1052 }
1053}
1054
1055void dt_exif_img_check_additional_tags(dt_image_t *img, const char *filename)
1056{
1057 try
1058 {
1059 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
1060 if(!image.get()) return;
1061 image->readMetadata();
1062 Exiv2::ExifData &exifData = image->exifData();
1063 if(!exifData.empty())
1064 {
1065 _check_usercrop(exifData, img);
1066 _check_dng_opcodes(exifData, img);
1067 /* Yes, _exif_decode_exif_data() also calls this, and no, it is not redundant. That
1068 * one may be handed an EXIF BLOB -- dt_exif_read_from_blob() -- and a blob routinely
1069 * arrives without the maker notes these readers need. This call opens the file, so it
1070 * is the one that can see them. Dropping it would leave every blob-fed path with no
1071 * embedded correction at all, which is a silent loss of a feature rather than a
1072 * visible failure. */
1073 _check_lens_correction_data(exifData, img);
1074 }
1075 return;
1076 }
1077 catch(const std::exception &e)
1078 {
1079 std::string s(e.what());
1080 std::cerr << "[exiv2 reading DefaultUserCrop] " << filename << ": " << s << std::endl;
1081 return;
1082 }
1083}
1084
1085static void _find_datetime_taken(Exiv2::ExifData &exifData,
1086 Exiv2::ExifData::const_iterator pos,
1087 char *exif_datetime_taken)
1088{
1089 if((FIND_EXIF_TAG("Exif.Image.DateTimeOriginal") || FIND_EXIF_TAG("Exif.Photo.DateTimeOriginal"))
1090 && pos->size() == DT_DATETIME_EXIF_LENGTH)
1091 {
1092 dt_strlcpy_to_utf8(exif_datetime_taken, DT_DATETIME_EXIF_LENGTH, pos, exifData);
1093 if(FIND_EXIF_TAG("Exif.Photo.SubSecTimeOriginal")
1094 && pos->size() > 1)
1095 {
1096 char msec[4];
1097 dt_strlcpy_to_utf8(msec, sizeof(msec), pos, exifData);
1098 dt_datetime_add_subsec_to_exif(exif_datetime_taken, DT_DATETIME_LENGTH, msec);
1099 }
1100 }
1101 else
1102 {
1103 *exif_datetime_taken = '\0';
1104 }
1105}
1106
1107static void _find_exif_maker(Exiv2::ExifData &exifData,
1108 Exiv2::ExifData::const_iterator pos,
1109 char *maker,
1110 const size_t m_size)
1111{
1112 // look for maker & model first so we can use that info later
1113 if(FIND_EXIF_TAG("Exif.Image.Make"))
1114 {
1115 dt_strlcpy_to_utf8(maker, m_size, pos, exifData);
1116 }
1117 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Make"))
1118 {
1119 dt_strlcpy_to_utf8(maker, m_size, pos, exifData);
1120 }
1121
1122 for(char *c = maker + m_size - 1; c > maker; c--)
1123 if(*c != ' ' && *c != '\0')
1124 {
1125 *(c + 1) = '\0';
1126 break;
1127 }
1128}
1129
1130static void _find_exif_model(Exiv2::ExifData &exifData,
1131 Exiv2::ExifData::const_iterator pos,
1132 char *model,
1133 const size_t m_size)
1134{
1135 if(FIND_EXIF_TAG("Exif.Image.Model"))
1136 {
1137 dt_strlcpy_to_utf8(model, m_size, pos, exifData);
1138 }
1139 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Model"))
1140 {
1141 dt_strlcpy_to_utf8(model, m_size, pos, exifData);
1142 }
1143
1144 for(char *c = model + m_size - 1; c > model; c--)
1145 if(*c != ' ' && *c != '\0')
1146 {
1147 *(c + 1) = '\0';
1148 break;
1149 }
1150}
1151
1152static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData)
1153{
1154 try
1155 {
1156 /* List of tag names taken from exiv2's printSummary() in actions.cpp */
1157 Exiv2::ExifData::const_iterator pos;
1158
1159 _find_exif_maker(exifData, pos, img->exif_maker, sizeof(img->exif_maker));
1160 _find_exif_model(exifData, pos, img->exif_model, sizeof(img->exif_model));
1161
1162 // Make sure we copy the exif make and model to the correct place if needed
1164
1165 /* Read shutter time */
1166 if((pos = Exiv2::exposureTime(exifData)) != exifData.end() && pos->size())
1167 {
1168 img->exif_exposure = pos->toFloat();
1169 }
1170 else if(FIND_EXIF_TAG("Exif.Photo.ShutterSpeedValue") || FIND_EXIF_TAG("Exif.Image.ShutterSpeedValue"))
1171 {
1172 // uf_strlcpy_to_utf8(uf->conf->shutterText, max_name, pos, exifData);
1173 img->exif_exposure = exp2f(-1.0f * pos->toFloat()); // convert from APEX value
1174 }
1175
1176 // Read exposure bias
1177 if(FIND_EXIF_TAG("Exif.Photo.ExposureBiasValue") || FIND_EXIF_TAG("Exif.Image.ExposureBiasValue"))
1178 {
1179 img->exif_exposure_bias = pos->toFloat();
1180 }
1181
1182 /* Read aperture */
1183 if((pos = Exiv2::fNumber(exifData)) != exifData.end() && pos->size())
1184 {
1185 img->exif_aperture = pos->toFloat();
1186 }
1187 else if(FIND_EXIF_TAG("Exif.Photo.ApertureValue") || FIND_EXIF_TAG("Exif.Image.ApertureValue"))
1188 {
1189 img->exif_aperture = exp2f(pos->toFloat() / 2.0f); // convert from APEX value
1190 }
1191
1192 /* Read ISO speed - Nikon happens to return a pair for Lo and Hi modes */
1193 if((pos = Exiv2::isoSpeed(exifData)) != exifData.end() && pos->size())
1194 {
1195 // if standard exif iso tag, use the old way of interpreting the return value to be more regression-save
1196 if(strcmp(pos->key().c_str(), "Exif.Photo.ISOSpeedRatings") == 0)
1197 {
1198 int isofield = pos->count() > 1 ? 1 : 0;
1199 img->exif_iso = pos->toFloat(isofield);
1200 }
1201 else
1202 {
1203 std::string str = pos->print();
1204 img->exif_iso = (float)std::atof(str.c_str());
1205 }
1206 }
1207 // some newer cameras support iso settings that exceed the 16 bit of exif's ISOSpeedRatings
1208 if(img->exif_iso == 65535 || img->exif_iso == 0)
1209 {
1210 if(FIND_EXIF_TAG("Exif.PentaxDng.ISO") || FIND_EXIF_TAG("Exif.Pentax.ISO"))
1211 {
1212 std::string str = pos->print();
1213 img->exif_iso = (float)std::atof(str.c_str());
1214 }
1215 else if((!g_strcmp0(img->exif_maker, "SONY") || !g_strcmp0(img->exif_maker, "Canon"))
1216 && FIND_EXIF_TAG("Exif.Photo.RecommendedExposureIndex"))
1217 {
1218 img->exif_iso = pos->toFloat();
1219 }
1220 }
1221
1222 /* Read focal length */
1223 if((pos = Exiv2::focalLength(exifData)) != exifData.end() && pos->size())
1224 {
1225 // This works around a bug in exiv2 the developers refuse to fix
1226 // For details see http://dev.exiv2.org/issues/1083
1227 if (pos->key() == "Exif.Canon.FocalLength" && pos->count() == 4)
1228 img->exif_focal_length = pos->toFloat(1);
1229 else
1230 img->exif_focal_length = pos->toFloat();
1231 }
1232
1233 // Read focal length in 35mm if available and try to calculate crop factor.
1234 if(FIND_EXIF_TAG("Exif.Photo.FocalLengthIn35mmFilm"))
1235 {
1236 const float focal_length_35mm = pos->toFloat();
1237 if(focal_length_35mm > 0.0f && img->exif_focal_length > 0.0f)
1238 img->exif_crop = focal_length_35mm / img->exif_focal_length;
1239 else
1240 img->exif_crop = 0.0f;
1241 }
1242
1243 // If the tag for the equivalent focal length is missing or contains zero,
1244 // let's try to get the crop factor by calculating the diagonal of the sensor:
1245 if(img->exif_crop == 0.0f && FIND_EXIF_TAG("Exif.Photo.FocalPlaneXResolution"))
1246 {
1247 float x_resolution = pos->toFloat();
1248 float y_resolution = 0.0f;
1249 if(FIND_EXIF_TAG("Exif.Photo.FocalPlaneYResolution"))
1250 y_resolution = pos->toFloat();
1251 guint res_unit = 1;
1252 if(FIND_EXIF_TAG("Exif.Photo.FocalPlaneResolutionUnit"))
1253 res_unit = pos->toLong();
1254 if(res_unit == 2) // inch
1255 {
1256 x_resolution /= 25.4f;
1257 y_resolution /= 25.4f;
1258 }
1259 else
1260 if(res_unit == 3) // centimeter
1261 {
1262 x_resolution /= 10.0f;
1263 y_resolution /= 10.0f;
1264 }
1265 guint image_width = 0;
1266 guint image_height = 0;
1267 // We are entering the zoo of image dimensions metadata.
1268 // Let's first try the Exif way of telling dimensions.
1269 // For Canon and Sigma cameras, these are the valid raw image
1270 // dimensions matching the the resolution tags.
1271 // For Fujifilm cameras, this will get the pixel dimensions
1272 // of the preview, not the sensor, because that's what the data
1273 // in the resolution tags on most Fujifilm cameras seems to be
1274 // calculated for.
1275 if(FIND_EXIF_TAG("Exif.Photo.PixelXDimension"))
1276 image_width = pos->toLong();
1277 if(FIND_EXIF_TAG("Exif.Photo.PixelYDimension"))
1278 image_height = pos->toLong();
1279 // Then try the Adobe DNG way of telling dimensions.
1280 // Exif.Image.ImageWidth/Length tags are also present in DNG files,
1281 // but may contain the pixel dimensions of the preview image, which in
1282 // this case will cause the diagonal calculation to be incorrect.
1283 if(image_width == 0 && FIND_EXIF_TAG("Exif.SubImage1.NewSubfileType"))
1284 {
1285 if(pos->toLong() == 0) // Primary image
1286 {
1287 if(FIND_EXIF_TAG("Exif.SubImage1.ImageWidth"))
1288 image_width = pos->toLong();
1289 if(FIND_EXIF_TAG("Exif.SubImage1.ImageLength"))
1290 image_height = pos->toLong();
1291 }
1292 }
1293 // The following tags in certain formats may contain pixel dimensions of
1294 // the preview instead of the full image, while resolution is calculated
1295 // relative to the full image dimensions. So we check them last.
1296 if(image_width == 0)
1297 {
1298 if(FIND_EXIF_TAG("Exif.Image.ImageWidth"))
1299 image_width = pos->toLong();
1300 if(FIND_EXIF_TAG("Exif.Image.ImageLength"))
1301 image_height = pos->toLong();
1302 }
1303
1304 const float x_size_mm = (float)image_width / x_resolution;
1305 const float y_size_mm = (float)image_height / y_resolution;
1306 if(image_width && image_height) // We've got the data and can calculate the crop factor
1307 {
1308 const float sensor_diagonal = dt_fast_hypotf(x_size_mm, y_size_mm);
1309 const float fullframe_diagonal = dt_fast_hypotf(36.0f, 24.0f);
1310 img->exif_crop = fullframe_diagonal / sensor_diagonal;
1311 }
1312 else
1313 img->exif_crop = 0.0f; // Will be shown as "no data" in the image information module
1314 }
1315
1316 if(_check_usercrop(exifData, img))
1317 {
1319 guint tagid = 0;
1320 char tagname[64];
1321 snprintf(tagname, sizeof(tagname), "darktable|mode|exif-crop");
1322 dt_tag_new(tagname, &tagid);
1323 dt_tag_attach(tagid, img->id, FALSE, FALSE);
1324 }
1325
1326 if(_check_dng_opcodes(exifData, img))
1327 {
1329 }
1330
1331 _check_lens_correction_data(exifData, img);
1332
1333 /*
1334 * Get the focus distance in meters.
1335 */
1336 if(Exiv2::testVersion(0, 27, 4) && FIND_EXIF_TAG("Exif.NikonLd4.LensID") && pos->toLong() != 0)
1337 {
1338 // Z lens, need to specifically look for the second instance of Exif.NikonLd4.FocusDistance
1339 // unless using Exiv2 0.28.x and later (also expanded to 2 bytes of precision since 0.28.1).
1340#if EXIV2_TEST_VERSION(0, 28, 0)
1341 if(FIND_EXIF_TAG("Exif.NikonLd4.FocusDistance2"))
1342 {
1343 float value = pos->toFloat();
1344 if(Exiv2::testVersion(0, 28, 1)) value /= 256.0f;
1345#else
1346 pos = exifData.end();
1347 for(auto it = exifData.begin(); it != exifData.end(); it++)
1348 {
1349 if(it->key() == "Exif.NikonLd4.FocusDistance") pos = it;
1350 }
1351 if(pos != exifData.end() && pos->size())
1352 {
1353 float value = pos->toFloat();
1354#endif
1355 img->exif_focus_distance = 0.01f * pow(10.0f, value / 40.0f);
1356 }
1357 }
1358 else if(FIND_EXIF_TAG("Exif.NikonLd2.FocusDistance") || FIND_EXIF_TAG("Exif.NikonLd3.FocusDistance")
1359 || (Exiv2::testVersion(0, 27, 4) && FIND_EXIF_TAG("Exif.NikonLd4.FocusDistance")))
1360 {
1361 float value = pos->toFloat();
1362 img->exif_focus_distance = 0.01f * pow(10.0f, value / 40.0f);
1363 }
1364 else if(FIND_EXIF_TAG("Exif.OlympusFi.FocusDistance"))
1365 {
1366 /* the distance is stored as a rational (fraction). according to
1367 * http://www.dpreview.com/forums/thread/1173960?page=4
1368 * some Olympus cameras have a wrong denominator of 10 in there while the nominator is always in mm.
1369 * thus we ignore the denominator
1370 * and divide with 1000.
1371 * "I've checked a number of E-1 and E-300 images, and I agree that the FocusDistance looks like it is
1372 * in mm for the E-1. However,
1373 * it looks more like cm for the E-300.
1374 * For both cameras, this value is stored as a rational. With the E-1, the denominator is always 1,
1375 * while for the E-300 it is 10.
1376 * Therefore, it looks like the numerator in both cases is in mm (which makes a bit of sense, in an odd
1377 * sort of way). So I think
1378 * what I will do in ExifTool is to take the numerator and divide by 1000 to display the focus distance
1379 * in meters."
1380 * -- Boardhead, dpreview forums in 2005
1381 */
1382 int nominator = pos->toRational(0).first;
1383 img->exif_focus_distance = fmax(0.0, (0.001 * nominator));
1384 }
1385 else if(FIND_EXIF_TAG("Exif.CanonFi.FocusDistanceUpper"))
1386 {
1387 const float FocusDistanceUpper = pos->toFloat();
1388 if(FocusDistanceUpper <= 0.0f || (int)FocusDistanceUpper >= 0xffff)
1389 {
1390 img->exif_focus_distance = 0.0f;
1391 }
1392 else
1393 {
1394 img->exif_focus_distance = FocusDistanceUpper / 100.0;
1395 if(FIND_EXIF_TAG("Exif.CanonFi.FocusDistanceLower"))
1396 {
1397 const float FocusDistanceLower = pos->toFloat();
1398 if(FocusDistanceLower > 0.0f && (int)FocusDistanceLower < 0xffff)
1399 {
1400 img->exif_focus_distance += FocusDistanceLower / 100.0;
1401 img->exif_focus_distance /= 2.0;
1402 }
1403 }
1404 }
1405 }
1406 else if(FIND_EXIF_TAG("Exif.CanonSi.SubjectDistance"))
1407 {
1408 img->exif_focus_distance = pos->toFloat() / 100.0;
1409 }
1410 else if((pos = Exiv2::subjectDistance(exifData)) != exifData.end() && pos->size())
1411 {
1412 img->exif_focus_distance = pos->toFloat();
1413 }
1414 else if(Exiv2::testVersion(0,27,2) && FIND_EXIF_TAG("Exif.Sony2Fp.FocusPosition2"))
1415 {
1416 const float focus_position = pos->toFloat();
1417
1418 if (focus_position && FIND_EXIF_TAG("Exif.Photo.FocalLengthIn35mmFilm")) {
1419 const float focal_length_35mm = pos->toFloat();
1420
1421 /* http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,3688.msg29653.html#msg29653 */
1422 img->exif_focus_distance = (pow(2, focus_position / 16 - 5) + 1) * focal_length_35mm / 1000;
1423 }
1424 }
1425
1426 /*
1427 * Read image orientation
1428 */
1429 if(FIND_EXIF_TAG("Exif.Image.Orientation"))
1430 {
1431 img->orientation = dt_image_orientation_to_flip_bits(pos->toLong());
1432 }
1433 else if(FIND_EXIF_TAG("Exif.PanasonicRaw.Orientation"))
1434 {
1435 img->orientation = dt_image_orientation_to_flip_bits(pos->toLong());
1436 }
1437 /* for e.g. Sinar backs the raw orientation is in a different subdirectory */
1438 if(FIND_EXIF_TAG("Exif.Thumbnail.PhotometricInterpretation") && (32803 == pos->toLong())
1439 && FIND_EXIF_TAG("Exif.Thumbnail.Orientation"))
1440 {
1441 img->orientation = dt_image_orientation_to_flip_bits(pos->toLong());
1442 }
1443
1444 /* read gps location */
1445 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSLatitude"))
1446 {
1447 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSLatitudeRef"));
1448 if(ref != exifData.end() && ref->size() && pos->count() == 3)
1449 {
1450 std::string sign_str = ref->toString();
1451 const char *sign = sign_str.c_str();
1452 double latitude = 0.0;
1453 if(dt_util_gps_rationale_to_number(pos->toRational(0).first, pos->toRational(0).second,
1454 pos->toRational(1).first, pos->toRational(1).second,
1455 pos->toRational(2).first, pos->toRational(2).second, sign[0], &latitude))
1456 img->geoloc.latitude = latitude;
1457 }
1458 }
1459
1460 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSLongitude"))
1461 {
1462 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSLongitudeRef"));
1463 if(ref != exifData.end() && ref->size() && pos->count() == 3)
1464 {
1465 std::string sign_str = ref->toString();
1466 const char *sign = sign_str.c_str();
1467 double longitude = 0.0;
1468 if(dt_util_gps_rationale_to_number(pos->toRational(0).first, pos->toRational(0).second,
1469 pos->toRational(1).first, pos->toRational(1).second,
1470 pos->toRational(2).first, pos->toRational(2).second, sign[0], &longitude))
1471 img->geoloc.longitude = longitude;
1472 }
1473 }
1474
1475 if(FIND_EXIF_TAG("Exif.GPSInfo.GPSAltitude"))
1476 {
1477 Exiv2::ExifData::const_iterator ref = exifData.findKey(Exiv2::ExifKey("Exif.GPSInfo.GPSAltitudeRef"));
1478 if(ref != exifData.end() && ref->size())
1479 {
1480 std::string sign_str = ref->toString();
1481 const char *sign = sign_str.c_str();
1482 double elevation = 0.0;
1483 if(dt_util_gps_elevation_to_number(pos->toRational(0).first, pos->toRational(0).second, sign[0], &elevation))
1484 img->geoloc.elevation = elevation;
1485 }
1486 }
1487
1488 /* Read lens name */
1489 if((FIND_EXIF_TAG("Exif.CanonCs.LensType")
1490 && pos->toLong() != 61182 // prefer the other tag for RF lenses
1491 && pos->toLong() != 0
1492 && pos->toLong() != 65535)
1493 || FIND_EXIF_TAG("Exif.Canon.LensModel"))
1494 {
1495 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1496 }
1497 else if(FIND_EXIF_TAG("Exif.PentaxDng.LensType"))
1498 {
1499 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1500 }
1501 else if(FIND_EXIF_TAG("Exif.Panasonic.LensType"))
1502 {
1503 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1504 }
1505 else if(FIND_EXIF_TAG("Exif.OlympusEq.LensType"))
1506 {
1507 /* For every Olympus camera Exif.OlympusEq.LensType is present. */
1508 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1509
1510 /* We have to check if Exif.OlympusEq.LensType has been translated by
1511 * exiv2. If it hasn't, fall back to Exif.OlympusEq.LensModel. */
1512 std::string lens(img->exif_lens);
1513 if(std::string::npos == lens.find_first_not_of(" 1234567890"))
1514 {
1515 /* Exif.OlympusEq.LensType contains only digits and spaces.
1516 * This means that exiv2 couldn't convert it to human readable
1517 * form. */
1518 if(FIND_EXIF_TAG("Exif.OlympusEq.LensModel"))
1519 {
1520 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1521 }
1522 /* Just in case Exif.OlympusEq.LensModel hasn't been found */
1523 else if(FIND_EXIF_TAG("Exif.Photo.LensModel"))
1524 {
1525 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1526 }
1527 fprintf(stderr, "[exif] Warning: lens \"%s\" unknown as \"%s\"\n", img->exif_lens, lens.c_str());
1528 }
1529 }
1530 else if(Exiv2::testVersion(0,27,4) && FIND_EXIF_TAG("Exif.NikonLd4.LensID") && pos->toLong() == 0)
1531 {
1532 /* Z body w/ FTZ adapter or recent F body (e.g. D780, D6) detected.
1533 * Prioritize the legacy ID lookup instead of Exif.Photo.LensModel included
1534 * in the default Exiv2::lensName() search below. */
1535 if(FIND_EXIF_TAG("Exif.NikonLd4.LensIDNumber"))
1536 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1537 }
1538 else if((pos = Exiv2::lensName(exifData)) != exifData.end() && pos->size())
1539 {
1540 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1541 }
1542
1543 /* Use pretty name for Canon RF & RF-S lenses (as exiftool/exiv2/lensfun) */
1544 if(g_str_has_prefix(img->exif_lens, "RF"))
1545 {
1546 char *pretty;
1547 if(img->exif_lens[2] == '-')
1548 pretty = g_strconcat("Canon RF-S ", &img->exif_lens[4], (char *)NULL);
1549 else
1550 pretty = g_strconcat("Canon RF ", &img->exif_lens[2], (char *)NULL);
1551 g_strlcpy(img->exif_lens, pretty, sizeof(img->exif_lens));
1552 dt_free(pretty);
1553 }
1554
1555 /* Capitalize Nikon Z-mount lenses properly for UI presentation */
1556 if(g_str_has_prefix(img->exif_lens, "NIKKOR") || g_str_has_prefix(img->exif_lens, "TAMRON"))
1557 {
1558 for(size_t i = 1; i <= 5; ++i)
1559 img->exif_lens[i] = g_ascii_tolower(img->exif_lens[i]);
1560 }
1561
1562 // finally the lens has only numbers and parentheses, let's try to use
1563 // Exif.Photo.LensModel if defined.
1564
1565 std::string lens(img->exif_lens);
1566 if(std::string::npos == lens.find_first_not_of(" (1234567890)")
1567 && FIND_EXIF_TAG("Exif.Photo.LensModel"))
1568 {
1569 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1570 }
1571
1572#if 0
1573 /* Read flash mode */
1574 if ( (pos=exifData.findKey(Exiv2::ExifKey("Exif.Photo.Flash")))
1575 != exifData.end() && pos->size())
1576 {
1577 uf_strlcpy_to_utf8(uf->conf->flashText, max_name, pos, exifData);
1578 }
1579 /* Read White Balance Setting */
1580 if ( (pos=exifData.findKey(Exiv2::ExifKey("Exif.Photo.WhiteBalance")))
1581 != exifData.end() && pos->size())
1582 {
1583 uf_strlcpy_to_utf8(uf->conf->whiteBalanceText, max_name, pos, exifData);
1584 }
1585#endif
1586
1587 char datetime[DT_DATETIME_LENGTH];
1588 _find_datetime_taken(exifData, pos, datetime);
1589 if(datetime[0] != '\0') dt_datetime_exif_to_img(img, datetime);
1590
1591 if(FIND_EXIF_TAG("Exif.Image.Artist"))
1592 {
1593 std::string str = pos->print(&exifData);
1594 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
1595 }
1596 else if(FIND_EXIF_TAG("Exif.Canon.OwnerName"))
1597 {
1598 std::string str = pos->print(&exifData);
1599 dt_metadata_set_import(img->id, "Xmp.dc.creator", str.c_str());
1600 }
1601
1602 // FIXME: Should the UserComment go into the description? Or do we need an extra field for this?
1603 if(FIND_EXIF_TAG("Exif.Photo.UserComment"))
1604 {
1605 std::string str = pos->print(&exifData);
1606 Exiv2::CommentValue value(str);
1607 std::string str2 = value.comment();
1608 if(str2 != "binary comment")
1609 dt_metadata_set_import(img->id, "Xmp.dc.description", str2.c_str());
1610 }
1611 else if(FIND_EXIF_TAG("Exif.Image.ImageDescription"))
1612 {
1613 std::string str = pos->print(&exifData);
1614 dt_metadata_set_import(img->id, "Xmp.dc.description", str.c_str());
1615 }
1616
1617 if(FIND_EXIF_TAG("Exif.Image.Copyright"))
1618 {
1619 std::string str = pos->print(&exifData);
1620 dt_metadata_set_import(img->id, "Xmp.dc.rights", str.c_str());
1621 }
1622
1623 if(FIND_EXIF_TAG("Exif.Image.Rating"))
1624 {
1625 const int stars = pos->toLong();
1626 dt_image_set_xmp_rating(img, stars);
1627 }
1628 else if(FIND_EXIF_TAG("Exif.Image.RatingPercent"))
1629 {
1630 const int stars = pos->toLong() * 5. / 100;
1631 dt_image_set_xmp_rating(img, stars);
1632 }
1633 else
1634 dt_image_set_xmp_rating(img, -2);
1635
1636 // read embedded color matrix as used in DNGs
1637 {
1638 float colmatrix[3][12];
1639 colmatrix[0][0] = colmatrix[1][0] = colmatrix[2][0] = NAN;
1641 img->d65_color_matrix[0] = NAN; // make sure for later testing
1642
1643 // fallback later via `find_temperature_from_raw_coeffs` if there is no valid illuminant
1644
1645 // The correction matrices are taken from
1646 // http://www.brucelindbloom.com - chromatic Adaption.
1647 // using Bradford method: found Illuminant -> D65
1648 const float correctmat[13][9] = {
1649 { 0.9555766, -0.0230393, 0.0631636, -0.0282895, 1.0099416, 0.0210077, 0.0122982, -0.0204830,
1650 1.3299098 }, // D50
1651 { 0.9726856, -0.0135482, 0.0361731, -0.0167463, 1.0049102, 0.0120598, 0.0070026, -0.0116372,
1652 1.1869548 }, // D55
1653 { 1.0206905, 0.0091588, -0.0228796, 0.0115005, 0.9984917, -0.0076762, -0.0043619, 0.0072053,
1654 0.8853432 }, // D75
1655 { 0.8446965, -0.1179225, 0.3948108, -0.1366303, 1.1041226, 0.1291718, 0.0798489, -0.1348999,
1656 3.1924009 }, // Standard light A
1657 { 0.9415037, -0.0321240, 0.0584672, -0.0428238, 1.0250998, 0.0203309, 0.0101511, -0.0161170,
1658 1.2847354 }, // Standard light B
1659 { 0.9904476, -0.0071683, -0.0116156, -0.0123712, 1.0155950, -0.0029282, -0.0035635, 0.0067697,
1660 0.9181569 }, // Standard light C
1661 { 0.9212269, -0.0449128, 0.1211620, -0.0553723, 1.0277243, 0.0403563, 0.0235086, -0.0391019,
1662 1.6390644 }, // Fluorescent (F2)
1663 // The following are calculated using the same Bradford method,
1664 // with xy coord from DNG SDK as reference -> XYZ -> D65
1665 { 0.8663030, -0.0913083, 0.2771784, -0.1090504, 1.0746895, 0.0913841, 0.0550856, -0.0924636,
1666 2.5119387 }, // ISO Studio Tungsten (3200K first converted to xy as DNG SDK does)
1667 { 1.0096114, 0.0061501, 0.0068113, 0.0102539, 0.9888663, 0.0015575, 0.0023119, -0.0044823,
1668 1.0525915 }, // DaylightFluorescent (F1)
1669 { 0.9554129, -0.0231280, 0.0637169, -0.0283629, 1.0099053, 0.0211824, 0.0124188, -0.0206922,
1670 1.3330592 }, // DayWhiteFluorescent (F8)
1671 { 0.9147843, -0.0492842, 0.1202810, -0.0622085, 1.034984, 0.0404480, 0.0228014, -0.0375807,
1672 1.6259804 }, // CoolWhiteFluorescent (F9)
1673 { 0.8805388, -0.0774890, 0.2293784, -0.0932136, 1.0589267, 0.0757827, 0.0453660, -0.0760107,
1674 2.2417979 }, // WhiteFluorescent (F3)
1675 { 0.8488316, -0.1107439, 0.3471428, -0.1310107, 1.0986874, 0.1141548, 0.0694025, -0.1167541,
1676 2.9109462 } // WarmWhiteFluorescent (F4)
1677 };
1678
1679 Exiv2::ExifData::const_iterator cm1_pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.ColorMatrix1"));
1680 if((cm1_pos != exifData.end()) && (cm1_pos->count() == 9))
1681 {
1682 for(int i = 0; i < 9; i++) colmatrix[0][i] = cm1_pos->toFloat(i);
1683
1684 if(FIND_EXIF_TAG("Exif.Image.CalibrationIlluminant1")) illu[0] = (dt_dng_illuminant_t) pos->toLong();
1685 }
1686
1687 Exiv2::ExifData::const_iterator cm2_pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.ColorMatrix2"));
1688 if((cm2_pos != exifData.end()) && (cm2_pos->count() == 9))
1689 {
1690 for(int i = 0; i < 9; i++) colmatrix[1][i] = cm2_pos->toFloat(i);
1691
1692 if(FIND_EXIF_TAG("Exif.Image.CalibrationIlluminant2")) illu[1] = (dt_dng_illuminant_t) pos->toLong();
1693 }
1694
1695 // So far the Exif.Image.CalibrationIlluminant3 tag and friends have not been implemented and there are no images to test
1696#if EXIV2_TEST_VERSION(0,27,4)
1697 Exiv2::ExifData::const_iterator cm3_pos = exifData.findKey(Exiv2::ExifKey("Exif.Image.ColorMatrix3"));
1698 if((cm3_pos != exifData.end()) && (cm3_pos->count() == 9))
1699 {
1700 for(int i = 0; i < 9; i++) colmatrix[2][i] = cm3_pos->toFloat(i);
1701
1702 if(FIND_EXIF_TAG("Exif.Image.CalibrationIlluminant3")) illu[2] = (dt_dng_illuminant_t) pos->toLong();
1703 }
1704#endif
1705
1706 int sel_illu = -1;
1707 int sel_temp = 0;
1708 const int D65temp = _illu_to_temp(DT_LS_D65);
1709 int delta_min = D65temp;
1710 // Which illuminant will be used for the color matrix?
1711 // We first try to find D65 or take the next higher
1712 for(int i = 0; i < 3; ++i)
1713 {
1714 int temp_cur = _illu_to_temp(illu[i]);
1715 int delta_cur = abs(temp_cur - D65temp);
1716 if((temp_cur > sel_temp) && (delta_cur <= delta_min))
1717 {
1718 sel_illu = i;
1719 sel_temp = temp_cur;
1720 delta_min = delta_cur;
1721 }
1722 }
1723 // If there is none defined we'll use the first valid color matrix
1724 // without correction, i.e. assume D65 (keep dt < 3.8 behaviour)
1725 // TODO: "Other" illuminant is currently unsupported
1726 if(sel_illu == -1)
1727 for(int i = 0; i < 3; ++i)
1728 {
1729 if((illu[i] == DT_LS_Unknown) && !isnan(colmatrix[i][0]))
1730 {
1731 sel_illu = i;
1732 sel_temp = D65temp;
1733 break;
1734 }
1735 }
1736
1737 if((sel_illu > -1) && (dt_get_debug_flags() & DT_DEBUG_IMAGEIO))
1738 {
1739 fprintf(stderr, "[exif] `%s` dng illuminant %i (%iK) selected from ", img->filename, illu[sel_illu], sel_temp);
1740 for(int i = 0; i < 3; i++)
1741 fprintf(stderr," -- [%i] %i (%iK)", i + 1, illu[i], _illu_to_temp(illu[i]));
1742 fprintf(stderr, "\n");
1743 }
1744
1745 // Take the found CalibrationIlluminant / ColorMatrix pair.
1746 // D65: just copy. Otherwise multiply by the specific correction matrix.
1747 if(sel_illu > -1)
1748 {
1749 // If no supported Illuminant is found/assumed it's better NOT to use any matrix.
1750 // The colorin module will write an error message and use a fallback matrix
1751 // instead of showing wrong colors.
1752 switch(illu[sel_illu])
1753 {
1754 case DT_LS_D50:
1755 mat3mul(img->d65_color_matrix, correctmat[0], colmatrix[sel_illu]);
1756 break;
1757 case DT_LS_D55:
1758 case DT_LS_Daylight:
1759 case DT_LS_FineWeather:
1760 case DT_LS_Flash:
1761 mat3mul(img->d65_color_matrix, correctmat[1], colmatrix[sel_illu]);
1762 break;
1763 case DT_LS_D75:
1764 case DT_LS_Shade:
1765 mat3mul(img->d65_color_matrix, correctmat[2], colmatrix[sel_illu]);
1766 break;
1767 case DT_LS_Tungsten:
1769 mat3mul(img->d65_color_matrix, correctmat[3], colmatrix[sel_illu]);
1770 break;
1772 mat3mul(img->d65_color_matrix, correctmat[4], colmatrix[sel_illu]);
1773 break;
1775 mat3mul(img->d65_color_matrix, correctmat[5], colmatrix[sel_illu]);
1776 break;
1777 case DT_LS_Fluorescent:
1778 mat3mul(img->d65_color_matrix, correctmat[6], colmatrix[sel_illu]);
1779 break;
1781 mat3mul(img->d65_color_matrix, correctmat[7], colmatrix[sel_illu]);
1782 break;
1784 mat3mul(img->d65_color_matrix, correctmat[8], colmatrix[sel_illu]);
1785 break;
1787 mat3mul(img->d65_color_matrix, correctmat[9], colmatrix[sel_illu]);
1788 break;
1790 mat3mul(img->d65_color_matrix, correctmat[10], colmatrix[sel_illu]);
1791 break;
1793 mat3mul(img->d65_color_matrix, correctmat[11], colmatrix[sel_illu]);
1794 break;
1796 mat3mul(img->d65_color_matrix, correctmat[12], colmatrix[sel_illu]);
1797 break;
1798 case DT_LS_D65:
1800 case DT_LS_Unknown: // exceptional fallback to keep dt < 3.8 behaviour
1801 for(int i = 0; i < 9; i++) img->d65_color_matrix[i] = colmatrix[sel_illu][i];
1802 break;
1803
1804 default:
1805 fprintf(stderr,"[exif] did not find a proper dng correction matrix for illuminant %i\n", illu[sel_illu]);
1806 break;
1807 }
1808 }
1809 }
1810
1811 // Finding out about DNG hdr and monochrome images can be done here while reading exif data.
1812 if(FIND_EXIF_TAG("Exif.Image.DNGVersion"))
1813 {
1814 int format = 1;
1815 int bps = 0;
1816 int spp = 0;
1817 int phi = 0;
1818
1819 if(FIND_EXIF_TAG("Exif.SubImage1.SampleFormat"))
1820 format = pos->toLong();
1821 else if(FIND_EXIF_TAG("Exif.Image.SampleFormat"))
1822 format = pos->toLong();
1823
1824 if(FIND_EXIF_TAG("Exif.SubImage1.BitsPerSample"))
1825 bps = pos->toLong();
1826 else if(FIND_EXIF_TAG("Exif.Image.BitsPerSample"))
1827 bps = pos->toLong();
1828
1829 if(FIND_EXIF_TAG("Exif.SubImage1.SamplesPerPixel"))
1830 spp = pos->toLong();
1831 else if(FIND_EXIF_TAG("Exif.Image.SamplesPerPixel"))
1832 spp = pos->toLong();
1833
1834 if(FIND_EXIF_TAG("Exif.SubImage1.PhotometricInterpretation"))
1835 phi = pos->toLong();
1836 else if(FIND_EXIF_TAG("Exif.Image.PhotometricInterpretation"))
1837 phi = pos->toLong();
1838
1839 if((format == 3) && (bps >= 16) && ((phi == 32803) || (phi == 34892)))
1840 img->flags |= DT_IMAGE_HDR;
1841
1842 if((spp == 1) && (phi == 34892))
1843 img->flags |= DT_IMAGE_MONOCHROME;
1844 }
1845
1846 // some files have the display colorspace explicitly set. try to read that. The Exif.Photo.ColorSpace
1847 // tag only exists in display-referred integer images, so gate on "not raw and not HDR-float"
1848 // rather than on DT_IMAGE_LDR: at this point the dynamic range of an ambiguous container (TIFF,
1849 // AVIF, HEIF) is not yet known (the extension can't tell, the buffer is not decoded), so the LDR
1850 // flag may legitimately be unset here even for an integer image.
1851 // tag absent -> leave colorspace as none
1852 // 0x01 -> sRGB
1853 // 0x02 -> AdobeRGB
1854 // 0xffff -> Uncalibrated
1855 // + Exif.Iop.InteroperabilityIndex of 'R03' -> AdobeRGB
1856 // + Exif.Iop.InteroperabilityIndex of 'R98' -> sRGB
1857 if(!dt_image_is_raw(img) && FIND_EXIF_TAG("Exif.Photo.ColorSpace"))
1858 {
1859 int colorspace = pos->toLong();
1860 if(colorspace == 0x01)
1862 else if(colorspace == 0x02)
1864 else if(colorspace == 0xffff)
1865 {
1866 if(FIND_EXIF_TAG("Exif.Iop.InteroperabilityIndex"))
1867 {
1868 std::string interop_index = pos->toString();
1869 if(interop_index == "R03")
1871 else if(interop_index == "R98")
1873 }
1874 }
1875 }
1876
1877 // Improve lens detection for Sony SAL lenses.
1878 if(FIND_EXIF_TAG("Exif.Sony2.LensID") && pos->toLong() != 65535 && pos->print().find('|') == std::string::npos)
1879 {
1880 dt_strlcpy_to_utf8(img->exif_lens, sizeof(img->exif_lens), pos, exifData);
1881 }
1882 // Workaround for an issue on newer Sony NEX cams.
1883 // The default EXIF field is not used by Sony to store lens data
1884 // http://dev.exiv2.org/issues/883
1885 // http://darktable.org/redmine/issues/8813
1886 // FIXME: This is still a workaround
1887 else if((!strncmp(img->exif_model, "NEX", 3)) || (!strncmp(img->exif_model, "ILCE", 4)))
1888 {
1889 snprintf(img->exif_lens, sizeof(img->exif_lens), "(unknown)");
1890 if(FIND_EXIF_TAG("Exif.Photo.LensModel"))
1891 {
1892 std::string str = pos->print(&exifData);
1893 snprintf(img->exif_lens, sizeof(img->exif_lens), "%s", str.c_str());
1894 }
1895 };
1896
1897 img->exif_inited = TRUE;
1898 return true;
1899 }
1900 catch(const std::exception &e)
1901 {
1902 std::string s(e.what());
1903 std::cerr << "[exiv2 _exif_decode_exif_data] " << img->filename << ": " << s << std::endl;
1904 return false;
1905 }
1906}
1907
1908// TODO: can this blob also contain xmp and iptc data?
1909int dt_exif_read_from_blob(dt_image_t *img, uint8_t *blob, const int size)
1910{
1911 try
1912 {
1913 Exiv2::ExifData exifData;
1914 Exiv2::ExifParser::decode(exifData, blob, size);
1915 bool res = _exif_decode_exif_data(img, exifData);
1916 return res ? 0 : 1;
1917 }
1918 catch(const std::exception &e)
1919 {
1920 std::string s(e.what());
1921 std::cerr << "[exiv2 dt_exif_read_from_blob] " << img->filename << ": " << s << std::endl;
1922 return 1;
1923 }
1924}
1925
1929int dt_exif_get_thumbnail(const char *path, uint8_t **buffer, size_t *size, char **mime_type, int *width, int *height, int min_width)
1930{
1931 try
1932 {
1933 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
1934 if(!image.get()) return 1;
1935 image->readMetadata();
1936
1937 // Get a list of preview images available in the image. The list is sorted
1938 // by the preview image pixel size, starting with the smallest preview.
1939 Exiv2::PreviewManager loader(*image);
1940 Exiv2::PreviewPropertiesList list = loader.getPreviewProperties();
1941 if(list.empty())
1942 {
1943 dt_print(DT_DEBUG_LIGHTTABLE, "[exiv2 dt_exif_get_thumbnail] couldn't find thumbnail for %s\n", path);
1944 return 1;
1945 }
1946
1947 // The list is ordered smallest-first, so the last entry is the largest preview -- but not
1948 // necessarily the cheapest one to decode. Several raw families (every DNG written by Adobe's
1949 // converter, Phase One IIQ, Hasselblad 3FR) put an uncompressed TIFF at the top of the list
1950 // and a JPEG below it; taking the largest unconditionally then costs a TIFF decode and a
1951 // buffer many times the size, for a preview that gets scaled down immediately. Prefer the
1952 // largest JPEG when there is one, and fall back to the largest of any type otherwise -- for
1953 // most DNGs there is no JPEG at all, and those still go through the TIFF path.
1954 Exiv2::PreviewProperties selected = list.back();
1955 for(auto it = list.rbegin(); it != list.rend(); ++it)
1956 {
1957 if(it->mimeType_ == "image/jpeg")
1958 {
1959 selected = *it;
1960 break;
1961 }
1962 }
1963
1964 // Get the selected preview image
1965 Exiv2::PreviewImage preview = loader.getPreviewImage(selected);
1966 const unsigned char *tmp = preview.pData();
1967 size_t _size = preview.size();
1968
1969 *size = _size;
1970 *width = preview.width();
1971 *height = preview.height();
1972 *mime_type = strdup(preview.mimeType().c_str());
1973 *buffer = (uint8_t *)malloc(_size);
1974 if(IS_NULL_PTR(*buffer)) {
1975 std::cerr << "[exiv2 dt_exif_get_thumbnail] couldn't allocate memory for thumbnail for " << path << std::endl;
1976 return 1;
1977 }
1978
1979 memcpy(*buffer, tmp, _size);
1980
1981 return 0;
1982 }
1983 catch(const std::exception &e)
1984 {
1985 std::string s(e.what());
1986 std::cerr << "[exiv2 dt_exif_get_thumbnail] " << path << ": " << s << std::endl;
1987 return 1;
1988 }
1989}
1990
1994int dt_exif_read(dt_image_t *img, const char *path)
1995{
1996 // Seed the provisional image-type flag (LDR / HDR / RAW, from the file extension) before we probe
1997 // dt_image_is_ldr() / dt_image_is_hdr() while decoding the EXIF below. This function can run on a
1998 // freshly dt_image_init()'d object (import preview, path-pattern expansion) long before the buffer
1999 // is decoded and dt_image_buffer_resolve_flags() sets the authoritative datatype-derived flags.
2000 // Only seed when nothing is classified yet, so a DB-loaded / already-resolved image is untouched.
2002 {
2003 const char *ext = g_strrstr(path, ".");
2004 if(ext) img->flags |= dt_image_flags_from_extension(ext + 1);
2005 }
2006
2007 // at least set datetime taken to something useful in case there is no exif data in this file (pfm, png,
2008 // ...)
2009 struct stat statbuf;
2010
2011 if(!stat(path, &statbuf))
2012 {
2013 dt_datetime_unix_to_img(img, &statbuf.st_mtime);
2014 }
2015
2016 try
2017 {
2018 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
2019 if(!image.get()) return 1;
2020 image->readMetadata();
2021 bool res = true;
2022
2023 // EXIF metadata
2024 Exiv2::ExifData &exifData = image->exifData();
2025 if(!exifData.empty())
2026 {
2027 res = _exif_decode_exif_data(img, exifData);
2028 }
2029 else
2030 img->exif_inited = 1;
2031
2032 // IPTC metadata.
2033 Exiv2::IptcData &iptcData = image->iptcData();
2034 if(!iptcData.empty()) res = _exif_decode_iptc_data(img, iptcData) && res;
2035
2036 // XMP metadata
2037 Exiv2::XmpData &xmpData = image->xmpData();
2038 if(!xmpData.empty())
2039 res = dt_exif_decode_xmp_data(img, xmpData, -1, true) && res;
2040
2041 // Initialize size - don't wait for full raw to be loaded to get this
2042 // information. If use_embedded_thumbnail is set, it will take a
2043 // change in development history to have this information
2044 img->height = image->pixelHeight();
2045 img->width = image->pixelWidth();
2046
2047 return res ? 0 : 1;
2048 }
2049 catch(const std::exception &e)
2050 {
2051 std::string s(e.what());
2052 std::cerr << "[exiv2 dt_exif_read] " << path << ": " << s << std::endl;
2053 return 1;
2054 }
2055}
2056
2057int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
2058{
2059 try
2060 {
2061 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
2062 if(!image.get()) return 1;
2063 image->readMetadata();
2064 Exiv2::ExifData &imgExifData = image->exifData();
2065 Exiv2::ExifData blobExifData;
2066 Exiv2::ExifParser::decode(blobExifData, blob, size);
2067 Exiv2::ExifData::const_iterator end = blobExifData.end();
2068 Exiv2::ExifData::iterator it;
2069 for(Exiv2::ExifData::const_iterator i = blobExifData.begin(); i != end; ++i)
2070 {
2071 // add() does not override! we need to delete existing key first.
2072 Exiv2::ExifKey key(i->key());
2073 if((it = imgExifData.findKey(key)) != imgExifData.end()) imgExifData.erase(it);
2074
2075 imgExifData.add(Exiv2::ExifKey(i->key()), &i->value());
2076 }
2077
2078 {
2079 // Remove thumbnail
2080 static const char *keys[] = {
2081 "Exif.Thumbnail.Compression",
2082 "Exif.Thumbnail.XResolution",
2083 "Exif.Thumbnail.YResolution",
2084 "Exif.Thumbnail.ResolutionUnit",
2085 "Exif.Thumbnail.JPEGInterchangeFormat",
2086 "Exif.Thumbnail.JPEGInterchangeFormatLength"
2087 };
2088 static const guint n_keys = G_N_ELEMENTS(keys);
2089 dt_remove_exif_keys(imgExifData, keys, n_keys);
2090 }
2091
2092 // only compressed images may set PixelXDimension and PixelYDimension
2093 if(!compressed)
2094 {
2095 static const char *keys[] = {
2096 "Exif.Photo.PixelXDimension",
2097 "Exif.Photo.PixelYDimension"
2098 };
2099 static const guint n_keys = G_N_ELEMENTS(keys);
2100 dt_remove_exif_keys(imgExifData, keys, n_keys);
2101 }
2102
2103 imgExifData.sortByTag();
2104 image->writeMetadata();
2105 }
2106 catch(const std::exception &e)
2107 {
2108 std::string s(e.what());
2109 std::cerr << "[exiv2 dt_exif_write_blob] " << path << ": " << s << std::endl;
2110 return 0;
2111 }
2112 return 1;
2113}
2114
2115// encode binary blob into text:
2116char *dt_exif_xmp_encode(const unsigned char *input, const int len, int *output_len)
2117{
2118#define COMPRESS_THRESHOLD 100
2119
2120 gboolean do_compress = FALSE;
2121
2122 // if input data field exceeds a certain size we compress it and convert to base64;
2123 // main reason for compression: make more xmp data fit into 64k segment within
2124 // JPEG output files.
2125 char *config = dt_conf_get_string("compress_xmp_tags");
2126 if(config)
2127 {
2128 if(!strcmp(config, "always"))
2129 do_compress = TRUE;
2130 else if((len > COMPRESS_THRESHOLD) && !strcmp(config, "only large entries"))
2131 do_compress = TRUE;
2132 else
2133 do_compress = FALSE;
2134 dt_free(config);
2135 }
2136
2137 return dt_exif_xmp_encode_internal(input, len, output_len, do_compress);
2138
2139#undef COMPRESS_THRESHOLD
2140}
2141
2142char *dt_exif_xmp_encode_internal(const unsigned char *input, const int len, int *output_len, gboolean do_compress)
2143{
2144 char *output = NULL;
2145
2146 if(do_compress)
2147 {
2148 int result;
2149 uLongf destLen = compressBound(len);
2150 unsigned char *buffer1 = (unsigned char *)malloc(destLen);
2151
2152 result = compress(buffer1, &destLen, input, len);
2153
2154 if(result != Z_OK)
2155 {
2156 dt_free(buffer1);
2157 return NULL;
2158 }
2159
2160 // we store the compression factor
2161 const int factor = MIN(len / destLen + 1, 99);
2162
2163 char *buffer2 = (char *)g_base64_encode(buffer1, destLen);
2164 dt_free(buffer1);
2165 if(IS_NULL_PTR(buffer2)) return NULL;
2166
2167 int outlen = strlen(buffer2) + 5; // leading "gz" + compression factor + base64 string + trailing '\0'
2168 output = (char *)malloc(outlen);
2169 if(IS_NULL_PTR(output))
2170 {
2171 dt_free(buffer2);
2172 return NULL;
2173 }
2174
2175 output[0] = 'g';
2176 output[1] = 'z';
2177 output[2] = factor / 10 + '0';
2178 output[3] = factor % 10 + '0';
2179 g_strlcpy(output + 4, buffer2, outlen);
2180 dt_free(buffer2);
2181
2182 if(output_len) *output_len = outlen;
2183 }
2184 else
2185 {
2186 const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
2187
2188 output = (char *)malloc(2 * len + 1);
2189 if(IS_NULL_PTR(output)) return NULL;
2190
2191 if(output_len) *output_len = 2 * len + 1;
2192
2193 for(int i = 0; i < len; i++)
2194 {
2195 const int hi = input[i] >> 4;
2196 const int lo = input[i] & 15;
2197 output[2 * i] = hex[hi];
2198 output[2 * i + 1] = hex[lo];
2199 }
2200 output[2 * len] = '\0';
2201 }
2202
2203 return output;
2204}
2205
2206// and back to binary
2207unsigned char *dt_exif_xmp_decode(const char *input, const int len, int *output_len)
2208{
2209 unsigned char *output = NULL;
2210
2211 // check if data is in compressed format
2212 if(!strncmp(input, "gz", 2))
2213 {
2214 // we have compressed data in base64 representation with leading "gz"
2215
2216 // get stored compression factor so we know the needed buffer size for uncompress
2217 const float factor = 10 * (input[2] - '0') + (input[3] - '0');
2218
2219 // get a rw copy of input buffer omitting leading "gz" and compression factor
2220 unsigned char *buffer = (unsigned char *)strdup(input + 4);
2221 if(IS_NULL_PTR(buffer)) return NULL;
2222
2223 // decode from base64 to compressed binary
2224 gsize compressed_size;
2225 g_base64_decode_inplace((char *)buffer, &compressed_size);
2226
2227 // do the actual uncompress step
2228 int result = Z_BUF_ERROR;
2229 uLongf bufLen = factor * compressed_size;
2230 uLongf destLen;
2231
2232 // we know the actual compression factor but if that fails we re-try with
2233 // increasing buffer sizes, eg. we don't know (unlikely) factors > 99
2234 do
2235 {
2236 if(output)
2237 {
2238 dt_free(output);
2239 }
2240 output = (unsigned char *)malloc(bufLen);
2241 if(IS_NULL_PTR(output)) break;
2242
2243 destLen = bufLen;
2244
2245 result = uncompress(output, &destLen, buffer, compressed_size);
2246
2247 bufLen *= 2;
2248
2249 } while(result == Z_BUF_ERROR);
2250
2251
2252 dt_free(buffer);
2253
2254 if(result != Z_OK)
2255 {
2256 if(output)
2257 {
2258 dt_free(output);
2259 }
2260 return NULL;
2261 }
2262
2263 if(output_len) *output_len = destLen;
2264 }
2265 else
2266 {
2267// we have uncompressed data in hexadecimal ascii representation
2268
2269// ascii table:
2270// 48- 57 0-9
2271// 97-102 a-f
2272#define TO_BINARY(a) (a > 57 ? a - 97 + 10 : a - 48)
2273
2274 // make sure that we don't find any unexpected characters indicating corrupted data
2275 if(strspn(input, "0123456789abcdef") != strlen(input)) return NULL;
2276
2277 output = (unsigned char *)malloc(len / 2);
2278 if(IS_NULL_PTR(output)) return NULL;
2279
2280 if(output_len) *output_len = len / 2;
2281
2282 for(int i = 0; i < len / 2; i++)
2283 {
2284 const int hi = TO_BINARY(input[2 * i]);
2285 const int lo = TO_BINARY(input[2 * i + 1]);
2286 output[i] = (hi << 4) | lo;
2287 }
2288#undef TO_BINARY
2289 }
2290
2291 return output;
2292}
2293
2294static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos)
2295{
2296 // tags in array
2297 const int cnt = pos->count();
2298
2299 for(int i = 0; i < cnt; i++)
2300 {
2301 char tagbuf[1024];
2302 std::string pos_str = pos->toString(i);
2303 g_strlcpy(tagbuf, pos_str.c_str(), sizeof(tagbuf));
2304 int tagid = -1;
2305 char *tag = tagbuf;
2306 while(tag)
2307 {
2308 char *next_tag = strstr(tag, ",");
2309 if(next_tag) *(next_tag++) = 0;
2310 // check if tag is available, get its id:
2311 for(int k = 0; k < 2; k++)
2312 {
2313 const guint found = dt_tag_repository_find_by_name(tag);
2314 if(found > 0) tagid = (int)found;
2315
2316 if(tagid > 0) break;
2317
2318 fprintf(stderr, "[xmp_import] creating tag: %s\n", tag);
2319 // create this tag (increment id, leave icon empty), retry.
2321 }
2322 // associate image and tag.
2323 dt_tag_repository_attach(tagid, img->id);
2324
2325 tag = next_tag;
2326 }
2327 }
2328}
2329
2331{
2332 try
2333 {
2334 Exiv2::ExifData::const_iterator pos;
2335 Exiv2::ExifData exifData;
2336 Exiv2::ExifParser::decode(exifData, data, size);
2337 // clang-format off
2338 // 0x01 -> sRGB
2339 // 0x02 -> AdobeRGB
2340 // 0xffff -> Uncalibrated
2341 // + Exif.Iop.InteroperabilityIndex of 'R03' -> AdobeRGB
2342 // + Exif.Iop.InteroperabilityIndex of 'R98' -> sRGB
2343 // clang-format on
2344 if((pos = exifData.findKey(Exiv2::ExifKey("Exif.Photo.ColorSpace"))) != exifData.end() && pos->size())
2345 {
2346 int colorspace = pos->toLong();
2347 if(colorspace == 0x01)
2348 return DT_COLORSPACE_SRGB;
2349 else if(colorspace == 0x02)
2351 else if(colorspace == 0xffff)
2352 {
2353 if((pos = exifData.findKey(Exiv2::ExifKey("Exif.Iop.InteroperabilityIndex"))) != exifData.end()
2354 && pos->size())
2355 {
2356 std::string interop_index = pos->toString();
2357 if(interop_index == "R03")
2359 else if(interop_index == "R98")
2360 return DT_COLORSPACE_SRGB;
2361 }
2362 }
2363 }
2364
2365 return DT_COLORSPACE_DISPLAY; // nothing embedded
2366 }
2367 catch(const std::exception &e)
2368 {
2369 std::string s(e.what());
2370 std::cerr << "[exiv2 dt_exif_get_color_space] " << s << std::endl;
2371 return DT_COLORSPACE_DISPLAY;
2372 }
2373}
2374
2375void dt_exif_get_datetime_taken(const uint8_t *data, size_t size, char *datetime_taken)
2376{
2377 try
2378 {
2379 Exiv2::ExifData::const_iterator pos;
2380 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(data, size));
2381 image->readMetadata();
2382 Exiv2::ExifData &exifData = image->exifData();
2383
2384 _find_datetime_taken(exifData, pos, datetime_taken);
2385 }
2386 catch(const std::exception &e)
2387 {
2388 std::string s(e.what());
2389 std::cerr << "[exiv2 dt_exif_get_datetime_taken] " << s << std::endl;
2390 }
2391}
2392
2393static void dt_exif_log_handler(int log_level, const char *message)
2394{
2395 if(log_level >= Exiv2::LogMsg::level())
2396 {
2397 // We don't seem to need \n in the format string as exiv2 includes it
2398 // in the messages themselves
2399 dt_print(DT_DEBUG_CAMERA_SUPPORT, "[exiv2] %s", message);
2400 }
2401}
2402
2404{
2405 // preface the exiv2 messages with "[exiv2] "
2406 Exiv2::LogMsg::setHandler(&dt_exif_log_handler);
2407
2408 // ISOBMFF (CR3, AVIF, HEIF) is a build requirement -- src/CMakeLists.txt fails the
2409 // configure if the Exiv2 we link was not built with it -- so there is nothing to test
2410 // for here. On 0.27.x the support still has to be switched on at runtime; enableBMFF()
2411 // was removed in 0.28.0, where it is always on.
2412 #if !EXIV2_TEST_VERSION(0,28,0)
2413 Exiv2::enableBMFF();
2414 #endif
2415
2416 // XmpParser init/term are required on older exiv2, but are deprecated no-ops from 0.28+.
2417 #if !EXIV2_TEST_VERSION(0,28,0)
2418 Exiv2::XmpParser::initialize();
2419 #endif
2420 // this has to stay with the old url (namespace already propagated outside dt)
2421 Exiv2::XmpProperties::registerNs("http://darktable.sf.net/", "darktable");
2422 // check is Exiv2 version already knows these prefixes
2423 try
2424 {
2425 Exiv2::XmpProperties::propertyList("lr");
2426 }
2427 catch(const std::exception &e)
2428 {
2429 // if lightroom is not known register it
2430 Exiv2::XmpProperties::registerNs("http://ns.adobe.com/lightroom/1.0/", "lr");
2431 }
2432 try
2433 {
2434 Exiv2::XmpProperties::propertyList("exifEX");
2435 }
2436 catch(const std::exception &e)
2437 {
2438 // if exifEX is not known register it
2439 Exiv2::XmpProperties::registerNs("http://cipa.jp/exif/1.0/", "exifEX");
2440 }
2441}
2442
2444{
2445 // Keep explicit termination for older exiv2; deprecated no-op in 0.28+.
2446 #if !EXIV2_TEST_VERSION(0,28,0)
2447 Exiv2::XmpParser::terminate();
2448 #endif
2449}
2450
2451// clang-format off
2452// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
2453// vim: shiftwidth=2 expandtab tabstop=2 cindent
2454// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
2455// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_colorlabels_remove_labels(const int32_t imgid)
void dt_colorlabels_set_label(const int32_t imgid, const int color)
const float f
const int t
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
gboolean dt_image_is_raw(const dt_image_t *img)
dt_image_flags_t dt_image_flags_from_extension(const char *extension)
void dt_image_refresh_makermodel(dt_image_t *img)
gboolean dt_image_get_xmp_mode()
void dt_image_set_xmp_rating(dt_image_t *img, const int rating)
void dt_datetime_add_subsec_to_exif(char *exif, const size_t exif_size, const char *subsec)
Definition datetime.c:395
gboolean dt_datetime_unix_to_img(dt_image_t *img, const time_t *unix)
Definition datetime.c:199
void dt_datetime_exif_to_img(dt_image_t *img, const char *exif)
Definition datetime.c:243
#define DT_DATETIME_LENGTH
Definition datetime.h:38
#define DT_DATETIME_EXIF_LENGTH
Definition datetime.h:39
void dt_dng_opcode_process_opcode_list_2(uint8_t *buf, uint32_t buf_size, dt_image_t *img)
Definition dng_opcode.c:59
GHashTable * names
GtkWidget* -> the name the application knows it by.
GtkWidget * preview
what the selected row actually captures
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * status
result of the last capture
const int res
Definition dtpthread.h:351
bool dt_exif_read_exif_tag(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator *pos, string key)
Read one EXIF tag into pos, FALSE if the image does not carry it.
Definition exif.cc:676
unsigned char * dt_exif_xmp_decode(const char *input, const int len, int *output_len)
Definition exif.cc:2207
static bool _usercrop_candidates_agree(const dt_boundingbox_t a, const dt_boundingbox_t b)
Definition exif.cc:737
dt_colorspaces_color_profile_type_t dt_exif_get_color_space(const uint8_t *data, size_t size)
Definition exif.cc:2330
int dt_exif_read_from_blob(dt_image_t *img, uint8_t *blob, const int size)
Definition exif.cc:1909
void dt_exif_get_datetime_taken(const uint8_t *data, size_t size, char *datetime_taken)
Definition exif.cc:2375
#define FIND_IPTC_TAG(key)
Definition exif.cc:594
#define FIND_XMP_TAG(key)
Definition exif.cc:422
void dt_exif_set_exiv2_taglist()
Definition exif.cc:271
void dt_exif_init()
Definition exif.cc:2403
static int _illu_to_temp(dt_dng_illuminant_t illu)
Definition exif.cc:228
int dt_exif_read(dt_image_t *img, const char *path)
Definition exif.cc:1994
static void dt_exif_log_handler(int log_level, const char *message)
Definition exif.cc:2393
static void _get_xmp_tags(const char *prefix, GList **taglist)
Definition exif.cc:215
static bool _check_usercrop(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:751
char * dt_exif_xmp_encode_internal(const unsigned char *input, const int len, int *output_len, gboolean do_compress)
Definition exif.cc:2142
static bool _read_fuji_11coef(Exiv2::ExifData::const_iterator posd, Exiv2::ExifData::const_iterator posc, Exiv2::ExifData::const_iterator posv, ls_vendor_fuji_t *f)
Definition exif.cc:895
bool dt_exif_decode_xmp_data(dt_image_t *img, Exiv2::XmpData &xmpData, int version, bool exif_read)
Apply one XMP packet's metadata, tags and colour labels to img.
Definition exif.cc:428
static bool _read_fuji_9coef(Exiv2::ExifData::const_iterator posd, Exiv2::ExifData::const_iterator posc, Exiv2::ExifData::const_iterator posv, ls_vendor_fuji_t *f)
Definition exif.cc:876
#define FIND_EXIF_TAG(key)
Definition exif.cc:691
void dt_exif_read_usercrop(dt_image_t *img, const char *filename)
Definition exif.cc:1031
static bool dt_exif_read_xmp_tag(Exiv2::XmpData &xmpData, Exiv2::XmpData::iterator *pos, string key)
Definition exif.cc:409
static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData)
Definition exif.cc:1152
static const char * _get_exiv2_type(const int type)
Definition exif.cc:150
char * dt_exif_xmp_encode(const unsigned char *input, const int len, int *output_len)
Definition exif.cc:2116
static gboolean _check_dng_opcodes(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:805
int dt_exif_get_thumbnail(const char *path, uint8_t **buffer, size_t *size, char **mime_type, int *width, int *height, int min_width)
Definition exif.cc:1929
static void _check_lens_correction_olympus(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:962
void dt_exif_img_check_additional_tags(dt_image_t *img, const char *filename)
Definition exif.cc:1055
static void _find_exif_model(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *model, const size_t m_size)
Definition exif.cc:1130
static void dt_strlcpy_to_utf8(char *dest, size_t dest_max, Exiv2::ExifData::const_iterator &pos, Exiv2::ExifData &exifData)
Definition exif.cc:372
static void _check_lens_correction_sony(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:845
void dt_exif_cleanup()
Definition exif.cc:2443
static dt_image_usercrop_status_t _read_usercrop_candidate(Exiv2::ExifData &exifData, const char *key, dt_boundingbox_t crop)
Definition exif.cc:710
static void _find_exif_maker(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *maker, const size_t m_size)
Definition exif.cc:1107
static bool dt_exif_read_iptc_tag(Exiv2::IptcData &iptcData, Exiv2::IptcData::const_iterator *pos, string key)
Definition exif.cc:581
static GList * exiv2_taglist
Definition exif.cc:126
static void _find_datetime_taken(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *exif_datetime_taken)
Definition exif.cc:1085
static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos)
Definition exif.cc:2294
void dt_remove_exif_keys(Exiv2::ExifData &exif, const char *keys[], unsigned int n_keys)
Strip the given EXIF keys from exif, ignoring any that are absent.
Definition exif.cc:389
const GList * dt_exif_get_exiv2_taglist()
Definition exif.cc:361
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
Definition exif.cc:2057
static void _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:995
#define COMPRESS_THRESHOLD
#define DT_IMAGE_USERCROP_EPSILON
Definition exif.cc:696
#define TO_BINARY(a)
static bool _exif_decode_iptc_data(dt_image_t *img, Exiv2::IptcData &iptcData)
Definition exif.cc:599
static void _check_lens_correction_fuji(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:921
static void _check_lens_correction_dng(Exiv2::ExifData &exifData, dt_image_t *img)
Definition exif.cc:826
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
dt_dng_illuminant_t
Definition exif.h:59
@ DT_LS_D65
Definition exif.h:77
@ DT_LS_DayWhiteFluorescent
Definition exif.h:69
@ DT_LS_Fluorescent
Definition exif.h:62
@ DT_LS_Daylight
Definition exif.h:61
@ DT_LS_D75
Definition exif.h:78
@ DT_LS_CloudyWeather
Definition exif.h:66
@ DT_LS_D50
Definition exif.h:79
@ DT_LS_StandardLightB
Definition exif.h:74
@ DT_LS_StandardLightC
Definition exif.h:75
@ DT_LS_CoolWhiteFluorescent
Definition exif.h:70
@ DT_LS_Shade
Definition exif.h:67
@ DT_LS_Flash
Definition exif.h:64
@ DT_LS_Tungsten
Definition exif.h:63
@ DT_LS_Unknown
Definition exif.h:60
@ DT_LS_WarmWhiteFluorescent
Definition exif.h:72
@ DT_LS_StandardLightA
Definition exif.h:73
@ DT_LS_FineWeather
Definition exif.h:65
@ DT_LS_D55
Definition exif.h:76
@ DT_LS_DaylightFluorescent
Definition exif.h:68
@ DT_LS_ISOStudioTungsten
Definition exif.h:80
@ DT_LS_WhiteFluorescent
Definition exif.h:71
The seam between metadata/exif.cc and common/xmp_sidecar.cc.
#define WIDEN(s)
@ DT_IMAGE_COLORSPACE_ADOBE_RGB
Definition image.h:194
@ DT_IMAGE_COLORSPACE_SRGB
Definition image.h:193
static dt_image_orientation_t dt_image_orientation_to_flip_bits(const int orient)
Definition image.h:702
float dt_boundingbox_t[4]
Definition image.h:83
@ DT_IMAGE_HAS_ADDITIONAL_DNG_TAGS
Definition image.h:145
@ DT_IMAGE_S_RAW
Definition image.h:147
@ DT_IMAGE_RAW
Definition image.h:124
@ DT_IMAGE_MONOCHROME
Definition image.h:142
@ DT_IMAGE_HDR
Definition image.h:126
@ DT_IMAGE_LDR
Definition image.h:122
dt_image_usercrop_status_t
Definition image.h:265
@ DT_IMAGE_USERCROP_IDENTITY
Definition image.h:268
@ DT_IMAGE_USERCROP_MALFORMED
Definition image.h:270
@ DT_IMAGE_USERCROP_CONFLICT
Definition image.h:271
@ DT_IMAGE_USERCROP_ABSENT
Definition image.h:267
@ DT_IMAGE_USERCROP_VALID
Definition image.h:269
const char * maker
const char * model
_lib_location_type_t type
Definition location.c:1
@ DT_DEBUG_LIGHTTABLE
Definition logging.h:60
@ DT_DEBUG_CAMERA_SUPPORT
Definition logging.h:66
@ DT_DEBUG_ALWAYS
Definition logging.h:49
@ DT_DEBUG_IMAGEIO
Definition logging.h:68
int32_t dt_get_debug_flags(void)
Definition darktable.c:2085
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
void void void dt_vprint(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
dt_print() that additionally requires DT_DEBUG_VERBOSE to be enabled, i.e. both -d <channel> and -d v...
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
static void mat3mul(float *const __restrict__ dest, const float *const __restrict__ m1, const float *const __restrict__ m2)
Definition math.h:163
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
void dt_metadata_clear(const GList *imgs, const gboolean undo_on)
char * key
const char * dt_metadata_get_key(const uint32_t keyid)
void dt_metadata_set_import(const int32_t imgid, const char *key, const char *value)
void dt_metadata_tags_changed(void)
Raise it. Internal to the module.
Everything this module says to the outside world: messages for the user, and the fact that the tag vo...
@ DT_METADATA_NUMBER
Definition metadata.h:57
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
size_t size
Definition mipmap_cache.c:3
const float factor
Definition pdf.h:91
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_ADOBERGB
@ DT_COLORSPACE_DISPLAY
The monitor profile – the one list entry that mutates after init.
@ DT_COLORSPACE_SRGB
sRGB – registered TWICE, and the two entries are not interchangeable.
static const dt_aligned_pixel_simd_t sign
Definition simd.h:118
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
double latitude
Definition image.h:332
double elevation
Definition image.h:332
double longitude
Definition image.h:332
float exif_exposure
Definition image.h:367
int32_t height
Definition image.h:397
float exif_focus_distance
Definition image.h:372
dt_boundingbox_t usercrop
Definition image.h:460
float exif_exposure_bias
Definition image.h:368
ls_vendor_data_t exif_correction
Definition image.h:469
float exif_iso
Definition image.h:370
int32_t exif_inited
Definition image.h:365
float exif_aperture
Definition image.h:369
dt_image_geoloc_t geoloc
Definition image.h:434
dt_image_usercrop_status_t usercrop_status
Definition image.h:461
int32_t flags
Definition image.h:401
dt_image_orientation_t orientation
Definition image.h:366
int32_t width
Definition image.h:397
float exif_focal_length
Definition image.h:371
char exif_maker[64]
Definition image.h:374
char exif_lens[128]
Definition image.h:376
float d65_color_matrix[9]
Definition image.h:421
char exif_model[64]
Definition image.h:375
dt_image_colorspace_t colorspace
Definition image.h:429
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:386
int32_t id
Definition image.h:401
float exif_crop
Definition image.h:373
gboolean dt_tag_repository_attach(const guint tagid, const int32_t imgid)
Attach tagid to imgid, at the end of the tag order.
guint dt_tag_repository_find_by_name(const char *name)
The id of the tag named name, or 0 when there is none.
guint dt_tag_repository_insert(const char *name)
Insert a tag named name and return its new id, or 0 on failure.
data.tags and main.tagged_images.
gboolean dt_tag_attach(const guint tagid, const int32_t imgid, const gboolean undo_on, const gboolean group_on)
Definition tags.c:377
gboolean dt_tag_set_tags(const GList *tags, const GList *img, const gboolean ignore_dt_tags, const gboolean clear_on, const gboolean undo_on)
Definition tags.c:398
gboolean dt_tag_new(const char *name, guint *tagid)
Definition tags.c:164
#define MIN(a, b)
Definition thinplate.c:32
gboolean dt_util_gps_elevation_to_number(const double r_1, const double r_2, char sign, double *result)
Definition utility.c:665
double dt_util_gps_string_to_number(const gchar *input)
Definition utility.c:609
gboolean dt_util_gps_rationale_to_number(const double r0_1, const double r0_2, const double r1_1, const double r1_2, const double r2_1, const double r2_2, char sign, double *result)
Definition utility.c:627
gchar * dt_util_foo_to_utf8(const char *string)
Definition utility.c:396
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)
Definition utility.c:99