[gimp] Issue #1437 - 2.10 Image Metadata "keywords" corrupt



commit d708ac0b214b9bec72e2038e5e7835fc72e5c884
Author: Michael Natterer <mitch gimp org>
Date:   Sun Jan 6 17:46:31 2019 +0100

    Issue #1437 - 2.10 Image Metadata "keywords" corrupt
    
    We were not taking into account tags that can appear multiple times,
    such as "keyword", they are handled by gexiv2 with the
    get_tag_multiple() and set_tag_multiple() functions.
    
    gimp_metadata_deserialize_text(): when deserializing our XML format,
    check if a tag is already set on the metadata as "multiple" and if yes
    retrieve it, append the new value and set it again.
    
    gimp_image_metadata_save_finish(): take care of "multiple" values when
    copying tags to new metadata created for saving.
    
    This should preserve all values across an "import, edit, export".
    
    Thing will still break when using the metadata editor, it doesn't
    handle multiple values at all, but that code is very hard to
    understand.

 libgimp/gimpimagemetadata.c | 49 ++++++++++++++++++++++++++++++---------------
 libgimpbase/gimpmetadata.c  | 48 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 70 insertions(+), 27 deletions(-)
---
diff --git a/libgimp/gimpimagemetadata.c b/libgimp/gimpimagemetadata.c
index 4e8b044494..f5f5e98603 100644
--- a/libgimp/gimpimagemetadata.c
+++ b/libgimp/gimpimagemetadata.c
@@ -380,6 +380,30 @@ gimp_image_metadata_save_prepare (gint32                 image_ID,
 }
 
 
+static void
+gimp_image_metadata_copy_tag (GExiv2Metadata *src,
+                              GExiv2Metadata *dest,
+                              const gchar    *tag)
+{
+  gchar **values = gexiv2_metadata_get_tag_multiple (src, tag);
+
+  if (values)
+    {
+      gexiv2_metadata_set_tag_multiple (dest, tag, (const gchar **) values);
+      g_strfreev (values);
+    }
+  else
+    {
+      gchar *value = gexiv2_metadata_get_tag_string (src, tag);
+
+      if (value)
+        {
+          gexiv2_metadata_set_tag_string (dest, tag, value);
+          g_free (value);
+        }
+    }
+}
+
 /**
  * gimp_image_metadata_save_finish:
  * @image_ID:  The image
@@ -410,7 +434,6 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
   gboolean        support_exif;
   gboolean        support_xmp;
   gboolean        support_iptc;
-  gchar          *value;
   gboolean        success = FALSE;
   gint            i;
 
@@ -446,11 +469,9 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
           if (! gexiv2_metadata_has_tag (new_g2metadata, exif_data[i]) &&
               gimp_metadata_is_tag_supported (exif_data[i], mime_type))
             {
-              value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
-                                                      exif_data[i]);
-              gexiv2_metadata_set_tag_string (new_g2metadata, exif_data[i],
-                                              value);
-              g_free (value);
+              gimp_image_metadata_copy_tag (GEXIV2_METADATA (metadata),
+                                            new_g2metadata,
+                                            exif_data[i]);
             }
         }
 
@@ -530,11 +551,9 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
           if (! gexiv2_metadata_has_tag (new_g2metadata, xmp_data[i]) &&
               gimp_metadata_is_tag_supported (xmp_data[i], mime_type))
             {
-              value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
-                                                      xmp_data[i]);
-              gexiv2_metadata_set_tag_string (new_g2metadata, xmp_data[i],
-                                              value);
-              g_free (value);
+              gimp_image_metadata_copy_tag (GEXIV2_METADATA (metadata),
+                                            new_g2metadata,
+                                            xmp_data[i]);
             }
         }
 
@@ -550,11 +569,9 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
           if (! gexiv2_metadata_has_tag (new_g2metadata, iptc_data[i]) &&
               gimp_metadata_is_tag_supported (iptc_data[i], mime_type))
             {
-              value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
-                                                      iptc_data[i]);
-              gexiv2_metadata_set_tag_string (new_g2metadata, iptc_data[i],
-                                              value);
-              g_free (value);
+              gimp_image_metadata_copy_tag (GEXIV2_METADATA (metadata),
+                                            new_g2metadata,
+                                            iptc_data[i]);
             }
         }
 
diff --git a/libgimpbase/gimpmetadata.c b/libgimpbase/gimpmetadata.c
index b67e472441..ad732389d1 100644
--- a/libgimpbase/gimpmetadata.c
+++ b/libgimpbase/gimpmetadata.c
@@ -616,20 +616,46 @@ gimp_metadata_deserialize_text (GMarkupParseContext  *context,
           decoded = g_base64_decode (value, &len);
 
           if (decoded[len - 1] == '\0')
-            gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
-                                            parse_data->name,
-                                            (const gchar *) decoded);
-
-          g_free (decoded);
+            {
+              g_free (value);
+              value = (gchar *) decoded;
+            }
+          else
+            {
+              g_clear_pointer (&value,   g_free);
+              g_clear_pointer (&decoded, g_free);
+            }
         }
-      else
+
+      if (value)
         {
-          gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
-                                          parse_data->name,
-                                          value);
-        }
+          GExiv2Metadata  *g2_metadata = GEXIV2_METADATA (parse_data->metadata);
+          gchar          **values;
 
-      g_free (value);
+          values = gexiv2_metadata_get_tag_multiple (g2_metadata,
+                                                     parse_data->name);
+
+          if (values)
+            {
+              guint length = g_strv_length (values);
+
+              values = g_renew (gchar *, values, length + 2);
+              values[length]     = value;
+              values[length + 1] = NULL;
+
+              gexiv2_metadata_set_tag_multiple (g2_metadata,
+                                                parse_data->name,
+                                                (const gchar **) values);
+              g_strfreev (values);
+            }
+          else
+            {
+              gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
+                                              parse_data->name,
+                                              value);
+              g_free (value);
+            }
+        }
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]