From d496f3785cf4585d5ec81756dd44ec9b67cef8ae Mon Sep 17 00:00:00 2001 From: Mario Zimmermann Date: Tue, 19 Mar 2024 18:42:05 +0100 Subject: [PATCH] cleanup exif data (#16491) * cleanup exif data See discussion in #16479 It turned out that exiv2 gives a whole zoo of manufacturer specific values for the white balance. In some cases where a camera value has no representation by exiv2, the color temperature value is returned, in a not well formated way with trailing spaces. Improvements/fixes: - remove trailing spaces - `not defined` and `unknown` are now treated as the darktable default `unnamed` - entries are now compared case-insensitive before they get written to the database. This avoids having duplicates like `Cloudy` and `CLOUDY` - if a numeric exif value `n` has no textual representation in exiv2 the returned string is `(n)` which is pretty much useless so it is discarded now - fixed a bug in `collection.c` where `strlen()` was used instead of `g_utf8_strlen()`. This failed on strings containing special characters (e.g. german umlauts) --- src/common/collection.c | 4 ++-- src/common/exif.cc | 50 +++++++++++++++++++++++++++++++++-------- src/common/image.c | 2 +- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/common/collection.c b/src/common/collection.c index 69e735273ec0..0367bec0f9ce 100644 --- a/src/common/collection.c +++ b/src/common/collection.c @@ -1245,12 +1245,12 @@ static gchar *_add_wildcards(const gchar *text) gchar *cam1 = NULL; gchar *cam2 = NULL; if(g_str_has_prefix(text, "\"")) - cam1 = g_utf8_substring(text, 1, strlen(text)); + cam1 = g_utf8_substring(text, 1, g_utf8_strlen(text, -1)); else cam1 = g_strdup_printf("%%%s", text); if(g_str_has_suffix(cam1, "\"")) - cam2 = g_utf8_substring(cam1, 0, strlen(cam1)-1); + cam2 = g_utf8_substring(cam1, 0, g_utf8_strlen(cam1, -1)-1); else cam2 = g_strdup_printf("%s%%", cam1); diff --git a/src/common/exif.cc b/src/common/exif.cc index d484bd9f6181..8c855e107941 100644 --- a/src/common/exif.cc +++ b/src/common/exif.cc @@ -425,8 +425,27 @@ static void _strlcpy_to_utf8(char *dest, size_t dest_max, { g_strlcpy(dest, str.c_str(), dest_max); } + g_strstrip(dest); } +// if a numerical exif value n has no string repsentation in exiv2 +// the returned string is a useless "(n)" which can be descarded +static void _exif_value_str(const int value, + char *dest, + size_t dest_max, + Exiv2::ExifData::const_iterator &pos, + Exiv2::ExifData &exifData) +{ + _strlcpy_to_utf8(dest, dest_max, pos, exifData); + gchar *str_value = g_strdup_printf("(%d)", value); + if(g_strcmp0(dest, str_value) == 0) + { + dest[0] = '\0'; + } + g_free(str_value); +} + + // function to remove known dt keys and subtrees from xmpdata, so not // to append them twice this should work because dt first reads all // known keys @@ -909,7 +928,7 @@ static gboolean _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_ const float kc = posc->toFloat(i + 1); const float kv = posv->toFloat(i + 1); // check that the knots position is the same for distortion, ca and vignetting, - if (kd != kc || kd != kv) + if(kd != kc || kd != kv) { img->exif_correction_type = CORRECTION_TYPE_NONE; break; @@ -943,7 +962,7 @@ static gboolean _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_ if(i != 0) kc = posc->toFloat(i); const float kv = posv->toFloat(i + 1); // check that the knots position is the same for distortion, ca and vignetting, - if (kd != kc || kd != kv) + if(kd != kc || kd != kv) { img->exif_correction_type = CORRECTION_TYPE_NONE; break; @@ -987,7 +1006,7 @@ static gboolean _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_ { const float kd = pos->toFloat(i); img->exif_correction_data.olympus.dist[i] = kd; - if (kd != 0 && i < 3) + if(kd != 0 && i < 3) { // Assume it's valid if any of the first three elements are nonzero. Ignore the // fourth element since the null value for no correction is '0 0 0 1' @@ -1010,7 +1029,7 @@ static gboolean _check_lens_correction_data(Exiv2::ExifData &exifData, dt_image_ { const float kc = pos->toFloat(i); img->exif_correction_data.olympus.ca[i] = kc; - if (kc != 0) + if(kc != 0) { img->exif_correction_type = CORRECTION_TYPE_OLYMPUS; img->exif_correction_data.olympus.has_ca = TRUE; @@ -1587,22 +1606,35 @@ static bool _exif_decode_exif_data(dt_image_t *img, Exiv2::ExifData &exifData) if((pos = Exiv2::whiteBalance(exifData)) != exifData.end() && pos->size()) { - _strlcpy_to_utf8(img->exif_whitebalance, sizeof(img->exif_whitebalance), pos, exifData); + const int value = pos->toLong(); + _exif_value_str(value, img->exif_whitebalance, sizeof(img->exif_whitebalance), pos, exifData); } if(FIND_EXIF_TAG("Exif.Photo.Flash")) { - _strlcpy_to_utf8(img->exif_flash, sizeof(img->exif_flash), pos, exifData); + const int value = pos->toLong(); + if(value != 0) + { + _strlcpy_to_utf8(img->exif_flash, sizeof(img->exif_flash), pos, exifData); + } } if(FIND_EXIF_TAG("Exif.Photo.ExposureProgram")) { - _strlcpy_to_utf8(img->exif_exposure_program, sizeof(img->exif_exposure_program), pos, exifData); + const int value = pos->toLong(); + if(value != 0) + { + _exif_value_str(value, img->exif_exposure_program, sizeof(img->exif_exposure_program), pos, exifData); + } } if(FIND_EXIF_TAG("Exif.Photo.MeteringMode")) { - _strlcpy_to_utf8(img->exif_metering_mode, sizeof(img->exif_metering_mode), pos, exifData); + const int value = pos->toLong(); + if(value != 0) + { + _exif_value_str(value, img->exif_metering_mode, sizeof(img->exif_metering_mode), pos, exifData); + } } char datetime[DT_DATETIME_LENGTH]; @@ -5027,7 +5059,7 @@ const std::pair, bool> getRegionNormalized( float y = yIt->toFloat() * imgHeight; /* MWG regions use (x,y) as the center of the region */ - if (regionType == RegionType::MWG) + if(regionType == RegionType::MWG) { x -= w/2; y -= h/2; diff --git a/src/common/image.c b/src/common/image.c index 1d9c5e6c26d1..d8666bed8824 100644 --- a/src/common/image.c +++ b/src/common/image.c @@ -3200,7 +3200,7 @@ static int32_t _image_get_set_name_id(const char *table, char *query = g_strdup_printf("SELECT id" " FROM main.%s" - " WHERE name = '%s'", + " WHERE LOWER(name) = LOWER('%s')", table, name);