73#define __STDC_FORMAT_MACROS
99#include <exiv2/exiv2.hpp>
120#if EXIV2_TEST_VERSION(0,28,0)
121#define AnyError Error
122#define toLong toInt64
128#if defined(_WIN32) && defined(EXV_UNICODE_PATH)
139 "[exiv2] path is not valid UTF-8, cannot convert it for Windows: `%s'\n",
utf8_path);
140 return std::wstring();
217 const Exiv2::XmpPropertyInfo *
pl = Exiv2::XmpProperties::propertyList(
prefix);
220 for (
int i = 0;
pl[
i].name_ != 0; ++
i)
277 const Exiv2::GroupInfo *
groupList = Exiv2::ExifTags::groupList();
301 const Exiv2::DataSet *
iptcEnvelopeList = Exiv2::IptcDataSets::envelopeRecordList();
354 catch (Exiv2::AnyError& e)
356 std::string s(e.what());
357 std::cerr <<
"[exiv2 taglist] " << s << std::endl;
395 Exiv2::ExifData::iterator pos;
396 while((pos = exif.findKey(Exiv2::ExifKey(keys[
i]))) != exif.end())
399 catch(
const std::exception &e)
413 return (*pos = xmpData.findKey(Exiv2::XmpKey(
key))) != xmpData.end() && (*pos)->size();
415 catch(
const std::exception &e)
417 std::string s(e.what());
418 std::cerr <<
"[exiv2 read_xmp_tag] " << s << std::endl;
422#define FIND_XMP_TAG(key) dt_exif_read_xmp_tag(xmpData, &pos, key)
436 Exiv2::XmpData::iterator pos;
442 if(version == -1 || version > 0)
466 const int stars = pos->toLong();
475 std::string label = pos->toString();
478 else if(label ==
"Yellow")
480 else if(label ==
"Green")
482 else if(label ==
"Blue")
484 else if(label ==
"Purple")
491 const int cnt = pos->count();
492 for(
int i = 0;
i <
cnt;
i++)
523 Exiv2::XmpData::const_iterator ref = xmpData.findKey(Exiv2::XmpKey(
"Xmp.exif.GPSAltitudeRef"));
524 if(ref != xmpData.end() && ref->size())
526 std::string
sign_str = ref->toString();
528 double elevation = 0.0;
538 char *lens =
strdup(pos->toString().c_str());
540 if(
strncmp(lens,
"lang=", 5) == 0)
554 char *datetime =
strdup(pos->toString().c_str());
567 catch(
const std::exception &e)
575 std::string s(e.what());
576 std::cerr <<
"[exiv2 dt_exif_decode_xmp_data] " << img->
filename <<
": " << s << std::endl;
587 catch(
const std::exception &e)
589 std::string s(e.what());
590 std::cerr <<
"[exiv2 read_iptc_tag] " << s << std::endl;
594#define FIND_IPTC_TAG(key) dt_exif_read_iptc_tag(iptcData, &pos, key)
603 Exiv2::IptcData::const_iterator pos;
606 if((pos =
iptcData.findKey(Exiv2::IptcKey(
"Iptc.Application2.Keywords"))) !=
iptcData.end())
610 std::string
key = pos->key();
611 if(
g_strcmp0(
key.c_str(),
"Iptc.Application2.Keywords"))
break;
612 std::string
str = pos->print();
624 std::string
str = pos->print();
629 std::string
str = pos->print();
634 std::string
str = pos->print();
639 std::string
str = pos->print();
644 std::string
str = pos->print();
655 gchar *time =
g_strdup(pos->toString().c_str());
668 catch(
const std::exception &e)
670 std::string s(e.what());
671 std::cerr <<
"[exiv2 _exif_decode_iptc_data] " << img->
filename <<
": " << s << std::endl;
677 Exiv2::ExifData::const_iterator *pos,
string key)
681 return (*pos =
exifData.findKey(Exiv2::ExifKey(
key)))
682 !=
exifData.end() && (*pos)->size();
684 catch(
const std::exception &e)
686 std::string s(e.what());
687 std::cerr <<
"[exiv2 read_exif_tag] " << s << std::endl;
691#define FIND_EXIF_TAG(key) dt_exif_read_exif_tag(exifData, &pos, key)
696#define DT_IMAGE_USERCROP_EPSILON 1e-6f
713 crop[0] = crop[1] = 0.f;
714 crop[2] = crop[3] = 1.f;
716 Exiv2::ExifData::const_iterator pos =
exifData.findKey(Exiv2::ExifKey(
key));
721 for(
int i = 0;
i < 4;
i++)
723 crop[
i] = pos->toFloat(
i);
731 if(crop[0] == 0.f && crop[1] == 0.f && crop[2] == 1.f && crop[3] == 1.f)
739 for(
int i = 0;
i < 4;
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]);
799 "[exif] image %d: ignoring DNG DefaultUserCrop, the camera framing metadata is %s\n",
808 Exiv2::ExifData::const_iterator pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.SubImage1.OpcodeList2"));
811 pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Image.OpcodeList2"));
815 pos->copy(data, Exiv2::invalidByteOrder);
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"));
833 pos->copy(data, Exiv2::invalidByteOrder);
847 Exiv2::ExifData::const_iterator
posd;
848 Exiv2::ExifData::const_iterator
posc;
849 Exiv2::ExifData::const_iterator
posv;
857 const int nc =
posd->toLong(0);
859 && (
int)
posd->count() >=
nc + 1
860 && (
int)
posc->count() >= 2 *
nc + 1
861 && (
int)
posv->count() >=
nc + 1)
864 for(
int i = 0;
i <
nc;
i++)
880 for(
int i = 0;
i < 9;
i++)
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;
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);
899 for(
int i = 0;
i < 11;
i++)
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;
906 f->distortion[
i] =
posd->toFloat(
i + 12);
914 f->ca_r[
i] =
posc->toFloat(
i + 10);
915 f->ca_b[
i] =
posc->toFloat(
i + 20);
917 f->vignetting[
i] =
posv->toFloat(
i + 12);
923 Exiv2::ExifData::const_iterator
posd;
924 Exiv2::ExifData::const_iterator
posc;
925 Exiv2::ExifData::const_iterator
posv;
926 Exiv2::ExifData::const_iterator
posm;
932 if(
posd->count() == 19 &&
posc->count() == 29 &&
posv->count() == 19)
941 else if(
posd->count() == 23 &&
posc->count() == 31 &&
posv->count() == 23)
956 && (
posm->toLong() == 2 ||
posm->toLong() == 4))
964 Exiv2::ExifData::const_iterator
posip;
968 for(
int i = 0;
i < 4;
i++)
972 if(
kd != 0.0f &&
i < 3)
982 for(
int i = 0;
i < 6;
i++)
1000 if(!Exiv2::testVersion(0, 27, 4))
return;
1025 static const char *
const names[] = {
"none",
"Sony",
"Fujifilm",
"DNG opcodes",
"Olympus" };
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();
1048 catch(
const std::exception &e)
1050 std::string s(e.what());
1051 std::cerr <<
"[exiv2 dt_exif_read_usercrop] " << filename <<
": " << s << std::endl;
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();
1077 catch(
const std::exception &e)
1079 std::string s(e.what());
1080 std::cerr <<
"[exiv2 reading DefaultUserCrop] " << filename <<
": " << s << std::endl;
1086 Exiv2::ExifData::const_iterator pos,
1087 char *exif_datetime_taken)
1103 *exif_datetime_taken =
'\0';
1108 Exiv2::ExifData::const_iterator pos,
1123 if(*c !=
' ' && *c !=
'\0')
1131 Exiv2::ExifData::const_iterator pos,
1145 if(*c !=
' ' && *c !=
'\0')
1157 Exiv2::ExifData::const_iterator pos;
1196 if(
strcmp(pos->key().c_str(),
"Exif.Photo.ISOSpeedRatings") == 0)
1198 int isofield = pos->count() > 1 ? 1 : 0;
1203 std::string
str = pos->print();
1212 std::string
str = pos->print();
1227 if (pos->key() ==
"Exif.Canon.FocalLength" && pos->count() == 4)
1265 guint image_width = 0;
1266 guint image_height = 0;
1276 image_width = pos->toLong();
1278 image_height = pos->toLong();
1283 if(image_width == 0 &&
FIND_EXIF_TAG(
"Exif.SubImage1.NewSubfileType"))
1285 if(pos->toLong() == 0)
1288 image_width = pos->toLong();
1290 image_height = pos->toLong();
1296 if(image_width == 0)
1299 image_width = pos->toLong();
1301 image_height = pos->toLong();
1306 if(image_width && image_height)
1321 snprintf(tagname,
sizeof(tagname),
"darktable|mode|exif-crop");
1336 if(Exiv2::testVersion(0, 27, 4) &&
FIND_EXIF_TAG(
"Exif.NikonLd4.LensID") && pos->toLong() != 0)
1340#if EXIV2_TEST_VERSION(0, 28, 0)
1343 float value = pos->toFloat();
1344 if(Exiv2::testVersion(0, 28, 1))
value /= 256.0f;
1349 if(
it->key() ==
"Exif.NikonLd4.FocusDistance") pos =
it;
1351 if(pos !=
exifData.end() && pos->size())
1353 float value = pos->toFloat();
1359 || (Exiv2::testVersion(0, 27, 4) &&
FIND_EXIF_TAG(
"Exif.NikonLd4.FocusDistance")))
1361 float value = pos->toFloat();
1382 int nominator = pos->toRational(0).first;
1410 else if((pos = Exiv2::subjectDistance(
exifData)) !=
exifData.end() && pos->size())
1414 else if(Exiv2::testVersion(0,27,2) &&
FIND_EXIF_TAG(
"Exif.Sony2Fp.FocusPosition2"))
1438 if(
FIND_EXIF_TAG(
"Exif.Thumbnail.PhotometricInterpretation") && (32803 == pos->toLong())
1447 Exiv2::ExifData::const_iterator ref =
exifData.findKey(Exiv2::ExifKey(
"Exif.GPSInfo.GPSLatitudeRef"));
1448 if(ref !=
exifData.end() && ref->size() && pos->count() == 3)
1450 std::string
sign_str = ref->toString();
1452 double latitude = 0.0;
1454 pos->toRational(1).first, pos->toRational(1).second,
1455 pos->toRational(2).first, pos->toRational(2).second,
sign[0], &latitude))
1462 Exiv2::ExifData::const_iterator ref =
exifData.findKey(Exiv2::ExifKey(
"Exif.GPSInfo.GPSLongitudeRef"));
1463 if(ref !=
exifData.end() && ref->size() && pos->count() == 3)
1465 std::string
sign_str = ref->toString();
1467 double longitude = 0.0;
1469 pos->toRational(1).first, pos->toRational(1).second,
1470 pos->toRational(2).first, pos->toRational(2).second,
sign[0], &longitude))
1477 Exiv2::ExifData::const_iterator ref =
exifData.findKey(Exiv2::ExifKey(
"Exif.GPSInfo.GPSAltitudeRef"));
1478 if(ref !=
exifData.end() && ref->size())
1480 std::string
sign_str = ref->toString();
1482 double elevation = 0.0;
1490 && pos->toLong() != 61182
1491 && pos->toLong() != 0
1492 && pos->toLong() != 65535)
1513 if(std::string::npos == lens.find_first_not_of(
" 1234567890"))
1530 else if(Exiv2::testVersion(0,27,4) &&
FIND_EXIF_TAG(
"Exif.NikonLd4.LensID") && pos->toLong() == 0)
1538 else if((pos = Exiv2::lensName(
exifData)) !=
exifData.end() && pos->size())
1558 for(
size_t i = 1;
i <= 5; ++
i)
1566 if(std::string::npos == lens.find_first_not_of(
" (1234567890)")
1574 if ( (pos=
exifData.findKey(Exiv2::ExifKey(
"Exif.Photo.Flash")))
1580 if ( (pos=
exifData.findKey(Exiv2::ExifKey(
"Exif.Photo.WhiteBalance")))
1608 if(
str2 !=
"binary comment")
1625 const int stars = pos->toLong();
1630 const int stars = pos->toLong() * 5. / 100;
1649 { 0.9555766, -0.0230393, 0.0631636, -0.0282895, 1.0099416, 0.0210077, 0.0122982, -0.0204830,
1651 { 0.9726856, -0.0135482, 0.0361731, -0.0167463, 1.0049102, 0.0120598, 0.0070026, -0.0116372,
1653 { 1.0206905, 0.0091588, -0.0228796, 0.0115005, 0.9984917, -0.0076762, -0.0043619, 0.0072053,
1655 { 0.8446965, -0.1179225, 0.3948108, -0.1366303, 1.1041226, 0.1291718, 0.0798489, -0.1348999,
1657 { 0.9415037, -0.0321240, 0.0584672, -0.0428238, 1.0250998, 0.0203309, 0.0101511, -0.0161170,
1659 { 0.9904476, -0.0071683, -0.0116156, -0.0123712, 1.0155950, -0.0029282, -0.0035635, 0.0067697,
1661 { 0.9212269, -0.0449128, 0.1211620, -0.0553723, 1.0277243, 0.0403563, 0.0235086, -0.0391019,
1665 { 0.8663030, -0.0913083, 0.2771784, -0.1090504, 1.0746895, 0.0913841, 0.0550856, -0.0924636,
1667 { 1.0096114, 0.0061501, 0.0068113, 0.0102539, 0.9888663, 0.0015575, 0.0023119, -0.0044823,
1669 { 0.9554129, -0.0231280, 0.0637169, -0.0283629, 1.0099053, 0.0211824, 0.0124188, -0.0206922,
1671 { 0.9147843, -0.0492842, 0.1202810, -0.0622085, 1.034984, 0.0404480, 0.0228014, -0.0375807,
1673 { 0.8805388, -0.0774890, 0.2293784, -0.0932136, 1.0589267, 0.0757827, 0.0453660, -0.0760107,
1675 { 0.8488316, -0.1107439, 0.3471428, -0.1310107, 1.0986874, 0.1141548, 0.0694025, -0.1167541,
1679 Exiv2::ExifData::const_iterator
cm1_pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Image.ColorMatrix1"));
1687 Exiv2::ExifData::const_iterator
cm2_pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Image.ColorMatrix2"));
1696#if EXIV2_TEST_VERSION(0,27,4)
1697 Exiv2::ExifData::const_iterator
cm3_pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Image.ColorMatrix3"));
1712 for(
int i = 0;
i < 3; ++
i)
1727 for(
int i = 0;
i < 3; ++
i)
1740 for(
int i = 0;
i < 3;
i++)
1820 format = pos->toLong();
1822 format = pos->toLong();
1825 bps = pos->toLong();
1827 bps = pos->toLong();
1830 spp = pos->toLong();
1832 spp = pos->toLong();
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();
1839 if((format == 3) && (
bps >= 16) && ((
phi == 32803) || (
phi == 34892)))
1842 if((spp == 1) && (
phi == 34892))
1859 int colorspace = pos->toLong();
1860 if(colorspace == 0x01)
1862 else if(colorspace == 0x02)
1864 else if(colorspace == 0xffff)
1878 if(
FIND_EXIF_TAG(
"Exif.Sony2.LensID") && pos->toLong() != 65535 && pos->print().find(
'|') == std::string::npos)
1900 catch(
const std::exception &e)
1902 std::string s(e.what());
1903 std::cerr <<
"[exiv2 _exif_decode_exif_data] " << img->
filename <<
": " << s << std::endl;
1918 catch(
const std::exception &e)
1920 std::string s(e.what());
1921 std::cerr <<
"[exiv2 dt_exif_read_from_blob] " << img->
filename <<
": " << s << std::endl;
1933 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(
WIDEN(path)));
1934 if(!image.get())
return 1;
1935 image->readMetadata();
1939 Exiv2::PreviewManager loader(*image);
1940 Exiv2::PreviewPropertiesList list = loader.getPreviewProperties();
1954 Exiv2::PreviewProperties
selected = list.back();
1955 for(
auto it = list.rbegin();
it != list.rend(); ++
it)
1957 if(
it->mimeType_ ==
"image/jpeg")
1975 std::cerr <<
"[exiv2 dt_exif_get_thumbnail] couldn't allocate memory for thumbnail for " << path << std::endl;
1983 catch(
const std::exception &e)
1985 std::string s(e.what());
1986 std::cerr <<
"[exiv2 dt_exif_get_thumbnail] " << path <<
": " << s << std::endl;
2018 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(
WIDEN(path)));
2019 if(!image.get())
return 1;
2020 image->readMetadata();
2024 Exiv2::ExifData &
exifData = image->exifData();
2033 Exiv2::IptcData &
iptcData = image->iptcData();
2037 Exiv2::XmpData &xmpData = image->xmpData();
2038 if(!xmpData.empty())
2044 img->
height = image->pixelHeight();
2045 img->
width = image->pixelWidth();
2049 catch(
const std::exception &e)
2051 std::string s(e.what());
2052 std::cerr <<
"[exiv2 dt_exif_read] " << path <<
": " << s << std::endl;
2061 std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(
WIDEN(path)));
2062 if(!image.get())
return 1;
2063 image->readMetadata();
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)
2072 Exiv2::ExifKey
key(
i->key());
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"
2095 static const char *keys[] = {
2096 "Exif.Photo.PixelXDimension",
2097 "Exif.Photo.PixelYDimension"
2104 image->writeMetadata();
2106 catch(
const std::exception &e)
2108 std::string s(e.what());
2109 std::cerr <<
"[exiv2 dt_exif_write_blob] " << path <<
": " << s << std::endl;
2118#define COMPRESS_THRESHOLD 100
2128 if(!
strcmp(config,
"always"))
2139#undef COMPRESS_THRESHOLD
2144 char *output =
NULL;
2177 output[2] =
factor / 10 +
'0';
2178 output[3] =
factor % 10 +
'0';
2186 const char hex[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' };
2188 output = (
char *)
malloc(2 * len + 1);
2193 for(
int i = 0;
i < len;
i++)
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];
2200 output[2 * len] =
'\0';
2209 unsigned char *output =
NULL;
2217 const float factor = 10 * (input[2] -
'0') + (input[3] -
'0');
2220 unsigned char *buffer = (
unsigned char *)
strdup(input + 4);
2272#define TO_BINARY(a) (a > 57 ? a - 97 + 10 : a - 48)
2277 output = (
unsigned char *)
malloc(len / 2);
2282 for(
int i = 0;
i < len / 2;
i++)
2286 output[
i] = (hi << 4) | lo;
2297 const int cnt = pos->count();
2299 for(
int i = 0;
i <
cnt;
i++)
2302 std::string
pos_str = pos->toString(
i);
2311 for(
int k = 0;
k < 2;
k++)
2314 if(found > 0) tagid = (int)found;
2316 if(tagid > 0)
break;
2334 Exiv2::ExifData::const_iterator pos;
2344 if((pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Photo.ColorSpace"))) !=
exifData.end() && pos->size())
2346 int colorspace = pos->toLong();
2347 if(colorspace == 0x01)
2349 else if(colorspace == 0x02)
2351 else if(colorspace == 0xffff)
2353 if((pos =
exifData.findKey(Exiv2::ExifKey(
"Exif.Iop.InteroperabilityIndex"))) !=
exifData.end()
2367 catch(
const std::exception &e)
2369 std::string s(e.what());
2370 std::cerr <<
"[exiv2 dt_exif_get_color_space] " << s << std::endl;
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();
2386 catch(
const std::exception &e)
2388 std::string s(e.what());
2389 std::cerr <<
"[exiv2 dt_exif_get_datetime_taken] " << s << std::endl;
2412 #if !EXIV2_TEST_VERSION(0,28,0)
2413 Exiv2::enableBMFF();
2417 #if !EXIV2_TEST_VERSION(0,28,0)
2418 Exiv2::XmpParser::initialize();
2421 Exiv2::XmpProperties::registerNs(
"http://darktable.sf.net/",
"darktable");
2425 Exiv2::XmpProperties::propertyList(
"lr");
2427 catch(
const std::exception &e)
2430 Exiv2::XmpProperties::registerNs(
"http://ns.adobe.com/lightroom/1.0/",
"lr");
2434 Exiv2::XmpProperties::propertyList(
"exifEX");
2436 catch(
const std::exception &e)
2439 Exiv2::XmpProperties::registerNs(
"http://cipa.jp/exif/1.0/",
"exifEX");
2446 #if !EXIV2_TEST_VERSION(0,28,0)
2447 Exiv2::XmpParser::terminate();
void dt_colorlabels_remove_labels(const int32_t imgid)
void dt_colorlabels_set_label(const int32_t imgid, const int color)
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)
gboolean dt_datetime_unix_to_img(dt_image_t *img, const time_t *unix)
void dt_datetime_exif_to_img(dt_image_t *img, const char *exif)
#define DT_DATETIME_LENGTH
#define DT_DATETIME_EXIF_LENGTH
void dt_dng_opcode_process_opcode_list_2(uint8_t *buf, uint32_t buf_size, dt_image_t *img)
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
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.
unsigned char * dt_exif_xmp_decode(const char *input, const int len, int *output_len)
static bool _usercrop_candidates_agree(const dt_boundingbox_t a, const dt_boundingbox_t b)
dt_colorspaces_color_profile_type_t dt_exif_get_color_space(const uint8_t *data, size_t size)
int dt_exif_read_from_blob(dt_image_t *img, uint8_t *blob, const int size)
void dt_exif_get_datetime_taken(const uint8_t *data, size_t size, char *datetime_taken)
#define FIND_IPTC_TAG(key)
#define FIND_XMP_TAG(key)
void dt_exif_set_exiv2_taglist()
static int _illu_to_temp(dt_dng_illuminant_t illu)
int dt_exif_read(dt_image_t *img, const char *path)
static void dt_exif_log_handler(int log_level, const char *message)
static void _get_xmp_tags(const char *prefix, GList **taglist)
static bool _check_usercrop(Exiv2::ExifData &exifData, dt_image_t *img)
char * dt_exif_xmp_encode_internal(const unsigned char *input, const int len, int *output_len, gboolean do_compress)
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)
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.
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)
#define FIND_EXIF_TAG(key)
void dt_exif_read_usercrop(dt_image_t *img, const char *filename)
static bool dt_exif_read_xmp_tag(Exiv2::XmpData &xmpData, Exiv2::XmpData::iterator *pos, string key)
static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData)
static const char * _get_exiv2_type(const int type)
char * dt_exif_xmp_encode(const unsigned char *input, const int len, int *output_len)
static gboolean _check_dng_opcodes(Exiv2::ExifData &exifData, dt_image_t *img)
int dt_exif_get_thumbnail(const char *path, uint8_t **buffer, size_t *size, char **mime_type, int *width, int *height, int min_width)
static void _check_lens_correction_olympus(Exiv2::ExifData &exifData, dt_image_t *img)
void dt_exif_img_check_additional_tags(dt_image_t *img, const char *filename)
static void _find_exif_model(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *model, const size_t m_size)
static void dt_strlcpy_to_utf8(char *dest, size_t dest_max, Exiv2::ExifData::const_iterator &pos, Exiv2::ExifData &exifData)
static void _check_lens_correction_sony(Exiv2::ExifData &exifData, dt_image_t *img)
static dt_image_usercrop_status_t _read_usercrop_candidate(Exiv2::ExifData &exifData, const char *key, dt_boundingbox_t crop)
static void _find_exif_maker(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *maker, const size_t m_size)
static bool dt_exif_read_iptc_tag(Exiv2::IptcData &iptcData, Exiv2::IptcData::const_iterator *pos, string key)
static GList * exiv2_taglist
static void _find_datetime_taken(Exiv2::ExifData &exifData, Exiv2::ExifData::const_iterator pos, char *exif_datetime_taken)
static void _exif_import_tags(dt_image_t *img, Exiv2::XmpData::iterator &pos)
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.
const GList * dt_exif_get_exiv2_taglist()
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
static void _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_t *img)
#define COMPRESS_THRESHOLD
#define DT_IMAGE_USERCROP_EPSILON
static bool _exif_decode_iptc_data(dt_image_t *img, Exiv2::IptcData &iptcData)
static void _check_lens_correction_fuji(Exiv2::ExifData &exifData, dt_image_t *img)
static void _check_lens_correction_dng(Exiv2::ExifData &exifData, dt_image_t *img)
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
@ DT_LS_DayWhiteFluorescent
@ DT_LS_CoolWhiteFluorescent
@ DT_LS_WarmWhiteFluorescent
@ DT_LS_DaylightFluorescent
@ DT_LS_ISOStudioTungsten
The seam between metadata/exif.cc and common/xmp_sidecar.cc.
@ DT_IMAGE_COLORSPACE_ADOBE_RGB
@ DT_IMAGE_COLORSPACE_SRGB
static dt_image_orientation_t dt_image_orientation_to_flip_bits(const int orient)
float dt_boundingbox_t[4]
@ DT_IMAGE_HAS_ADDITIONAL_DNG_TAGS
dt_image_usercrop_status_t
@ DT_IMAGE_USERCROP_IDENTITY
@ DT_IMAGE_USERCROP_MALFORMED
@ DT_IMAGE_USERCROP_CONFLICT
@ DT_IMAGE_USERCROP_ABSENT
@ DT_IMAGE_USERCROP_VALID
_lib_location_type_t type
@ DT_DEBUG_CAMERA_SUPPORT
int32_t dt_get_debug_flags(void)
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...
static void mat3mul(float *const __restrict__ dest, const float *const __restrict__ m1, const float *const __restrict__ m2)
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
dt_colorspaces_color_profile_type_t
@ 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
static const dt_aligned_pixel_simd_t value
float exif_focus_distance
dt_boundingbox_t usercrop
ls_vendor_data_t exif_correction
dt_image_usercrop_status_t usercrop_status
dt_image_orientation_t orientation
float d65_color_matrix[9]
dt_image_colorspace_t colorspace
char filename[DT_MAX_FILENAME_LEN]
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_util_gps_elevation_to_number(const double r_1, const double r_2, char sign, double *result)
double dt_util_gps_string_to_number(const gchar *input)
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)
gchar * dt_util_foo_to_utf8(const char *string)
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)