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



commit 4f9bde3bad007cc32f0328da8387653ffa99c6fe
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.
    
    (cherry picked from commit d708ac0b214b9bec72e2038e5e7835fc72e5c884)

 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 e99a680b78..3312e11b91 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 e5efbe5345..607112b4b6 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]