Skip to content

Commit a0af003

Browse files
committed
exif: do not blanket-delete all custom metadata on Xmp read
Through the call chain dt_image_import -> _image_import_internal -> dt_exif_xmp_read -> _exif_decode_xmp_data, the function _exif_decode_xmp_data would be called with exif_read == FALSE, causing it to delete all metadata which has previously been read in _exif_decode_exif_data (see the parent commit). The intent was likely to be able to update descriptions etc. which had been written through other programs in the Xmp files in darktable. In order to continue to support this use case, we do still remove Xmp-related tags if we don't find them in the sidecar, but only those (via a string match).
1 parent 3ca6248 commit a0af003

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

src/common/exif.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,6 @@ static bool _exif_decode_xmp_data(dt_image_t *img,
610610
if(version == -1 || version > 0)
611611
{
612612
dt_pthread_mutex_lock(&darktable.metadata_threadsafe);
613-
if(!exif_read) dt_metadata_clear(imgs, FALSE);
614613

615614
for(GList *iter = dt_metadata_get_list(); iter; iter = iter->next)
616615
{
@@ -629,6 +628,12 @@ static bool _exif_decode_xmp_data(dt_image_t *img,
629628
dt_metadata_set_import(img->id, metadata->tagname, value);
630629
free(adr);
631630
}
631+
else if(!exif_read && strstr(metadata->tagname, "Xmp.") == metadata->tagname)
632+
{
633+
// Only remove Xmp. metadata fields, do not touch metadata from other
634+
// sources (e.g. Exif.*).
635+
dt_metadata_unset(img->id, metadata->tagname, FALSE);
636+
}
632637
}
633638
dt_pthread_mutex_unlock(&darktable.metadata_threadsafe);
634639
}

src/common/metadata.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,34 @@ void dt_metadata_set_list_id(const GList *img,
838838
}
839839
}
840840

841+
void dt_metadata_unset(const dt_imgid_t imgid, const char *key, const gboolean undo_on)
842+
{
843+
if(!key || !dt_is_valid_imgid(imgid)) return;
844+
845+
int keyid = dt_metadata_get_keyid(key);
846+
if(keyid == -1) return;
847+
848+
GList *imgs = NULL;
849+
imgs = g_list_prepend(imgs, GINT_TO_POINTER(imgid));
850+
GList *undo = NULL;
851+
if(undo_on) dt_undo_start_group(darktable.undo, DT_UNDO_METADATA);
852+
853+
const gchar *ckey = g_strdup_printf("%d", keyid);
854+
GList *metadata = NULL;
855+
metadata = g_list_append(metadata, (gpointer)ckey);
856+
metadata = g_list_append(metadata, NULL);
857+
858+
_metadata_execute(imgs, metadata, &undo, undo_on, DT_MA_REMOVE);
859+
860+
g_list_free_full(metadata, g_free);
861+
g_list_free(imgs);
862+
if(undo_on)
863+
{
864+
dt_undo_record(darktable.undo, NULL, DT_UNDO_METADATA, undo, _pop_undo, _metadata_undo_data_free);
865+
dt_undo_end_group(darktable.undo);
866+
}
867+
}
868+
841869
gboolean dt_metadata_already_imported(const char *filename, const char *datetime)
842870
{
843871
if(!filename || !datetime)

src/common/metadata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ void dt_metadata_set_list(const GList *imgs, GList *key_value, const gboolean un
9898
if clear_on TRUE the image metadata are cleared before attaching the new ones*/
9999
void dt_metadata_set_list_id(const GList *img, const GList *metadata, const gboolean clear_on,
100100
const gboolean undo_on);
101+
/** Unset a specific metadata key for a specific image. Noop if the key isn't set. */
102+
void dt_metadata_unset(const dt_imgid_t imgid, const char *key, const gboolean undo_on);
101103
/** Get metadata (named keys) for a specific image, or all selected for an invalid imgid
102104
For keys which return a string, the caller has to make sure that it
103105
is freed after usage. With mutex lock. */

0 commit comments

Comments
 (0)