Skip to content

Commit

Permalink
cleanup exif data (#16491)
Browse files Browse the repository at this point in the history
* 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)
  • Loading branch information
zisoft committed Mar 19, 2024
1 parent 6fd35b8 commit d496f37
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/common/collection.c
Expand Up @@ -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);

Expand Down
50 changes: 41 additions & 9 deletions src/common/exif.cc
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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'
Expand All @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -5027,7 +5059,7 @@ const std::pair<std::array<float, 4>, 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;
Expand Down
2 changes: 1 addition & 1 deletion src/common/image.c
Expand Up @@ -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);

Expand Down

0 comments on commit d496f37

Please sign in to comment.