[gimp] plug-ins: refactor metadata saving in HEIF/AVIF plugin



commit 884611955adf687031b7f492146d42d67920e6a0
Author: Daniel Novomeský <dnovomesky gmail com>
Date:   Wed Mar 16 16:29:17 2022 +0100

    plug-ins: refactor metadata saving in HEIF/AVIF plugin
    
    The plug-in now use gimp_image_metadata_save_filter API

 plug-ins/common/file-heif.c | 274 ++++++++++----------------------------------
 1 file changed, 58 insertions(+), 216 deletions(-)
---
diff --git a/plug-ins/common/file-heif.c b/plug-ins/common/file-heif.c
index dfab9dbd91..649b20dbb0 100644
--- a/plug-ins/common/file-heif.c
+++ b/plug-ins/common/file-heif.c
@@ -1366,76 +1366,6 @@ load_image (GFile              *file,
   return image;
 }
 
-static const gchar *
-heifplugin_fix_xmp_tag (const gchar *tag)
-{
-  gchar *substring;
-
-  /* Due to problems using /Iptc4xmpExt namespace (/iptcExt is used
-   * instead by Exiv2) we replace all occurrences with /iptcExt which
-   * is valid but less common. Not doing so would cause saving xmp
-   * metadata to fail. This has to be done after getting the values
-   * from the source metadata since that source uses the original
-   * tag names and would otherwise return NULL as value.
-   * /Iptc4xmpExt length = 12
-   * /iptcExt     length =  8
-   */
-
-  substring = strstr (tag, "/Iptc4xmpExt");
-  while (substring)
-    {
-      gint len_tag = strlen (tag);
-      gint len_end;
-
-      len_end = len_tag - (substring - tag) - 12;
-      strncpy (substring, "/iptcExt", 8);
-      substring += 8;
-      /* Using memmove: we have overlapping source and dest */
-      memmove (substring, substring+4, len_end);
-      substring[len_end] = '\0';
-      g_debug ("Fixed tag value: %s", tag);
-
-      /* Multiple occurrences are possible: e.g.:
-       * Xmp.iptcExt.ImageRegion[3]/Iptc4xmpExt:RegionBoundary/Iptc4xmpExt:rbVertices[1]/Iptc4xmpExt:rbX
-       */
-      substring = strstr (tag, "/Iptc4xmpExt");
-    }
-  return tag;
-}
-
-static void
-heifplugin_image_metadata_copy_tag (GExiv2Metadata *src,
-                                    GExiv2Metadata *dest,
-                                    const gchar    *tag)
-{
-  gchar **values = gexiv2_metadata_try_get_tag_multiple (src, tag, NULL);
-
-  if (values)
-    {
-      gchar *temp_tag;
-
-      /* Xmp always seems to return multiple values */
-      if (g_str_has_prefix (tag, "Xmp."))
-        temp_tag = (gchar *) heifplugin_fix_xmp_tag (g_strdup (tag));
-      else
-        temp_tag = g_strdup (tag);
-
-      gexiv2_metadata_try_set_tag_multiple (dest, temp_tag, (const gchar **) values, NULL);
-      g_free (temp_tag);
-      g_strfreev (values);
-    }
-  else
-    {
-      gchar *value = gexiv2_metadata_try_get_tag_string (src, tag, NULL);
-
-      if (value)
-        {
-          gexiv2_metadata_try_set_tag_string (dest, tag, value, NULL);
-          g_free (value);
-        }
-    }
-}
-
 static struct heif_error
 write_callback (struct heif_context *ctx,
                 const void          *data,
@@ -2017,175 +1947,87 @@ save_image (GFile                        *file,
       return FALSE;
     }
 
-  /*  EXIF metadata  */
-  if (save_exif && metadata)
+  if (metadata && (save_exif || save_xmp))
     {
-      if (gexiv2_metadata_get_supports_exif (GEXIV2_METADATA (metadata)) &&
-          gexiv2_metadata_has_exif (GEXIV2_METADATA (metadata)))
+      GimpMetadata         *filtered_metadata;
+      GimpMetadataSaveFlags metadata_flags = 0;
+
+      if (save_exif)
         {
-          GimpMetadata   *new_exif_metadata = gimp_metadata_new ();
-          GExiv2Metadata *new_gexiv2metadata = GEXIV2_METADATA (new_exif_metadata);
-          GBytes         *raw_exif_data;
-          gchar         **exif_data = gexiv2_metadata_get_exif_tags (GEXIV2_METADATA (metadata));
-          guint           i;
+          metadata_flags |= GIMP_METADATA_SAVE_EXIF;
+        }
 
-          gexiv2_metadata_clear_exif (new_gexiv2metadata);
+      if (save_xmp)
+        {
+          metadata_flags |= GIMP_METADATA_SAVE_XMP;
+        }
 
-          for (i = 0; exif_data[i] != NULL; i++)
+      filtered_metadata = gimp_image_metadata_save_filter (image, "image/heif", metadata, metadata_flags, 
NULL, error);
+      if(! filtered_metadata)
+        {
+          if (error && *error)
             {
-              if (! gexiv2_metadata_has_tag (new_gexiv2metadata, exif_data[i]) &&
-                  gimp_metadata_is_tag_supported (exif_data[i], "image/heif"))
-                {
-                  heifplugin_image_metadata_copy_tag (GEXIV2_METADATA (metadata),
-                                                      new_gexiv2metadata,
-                                                      exif_data[i]);
-                }
+              g_printerr ("%s: error filtering metadata: %s",
+                          G_STRFUNC, (*error)->message);
+              g_clear_error (error);
             }
+        }
+      else
+        {
+          GExiv2Metadata *filtered_g2metadata = GEXIV2_METADATA (filtered_metadata);
 
-          g_strfreev (exif_data);
-
-          raw_exif_data = gexiv2_metadata_get_exif_data (new_gexiv2metadata, GEXIV2_BYTE_ORDER_LITTLE, 
error);
-          if (raw_exif_data)
+          /*  EXIF metadata  */
+          if (save_exif && gexiv2_metadata_has_exif (filtered_g2metadata))
             {
-              gsize exif_size = 0;
-              gconstpointer exif_buffer = g_bytes_get_data (raw_exif_data, &exif_size);
+              GBytes *raw_exif_data;
 
-              if (exif_size >= 4)
+              raw_exif_data = gexiv2_metadata_get_exif_data (filtered_g2metadata, GEXIV2_BYTE_ORDER_LITTLE, 
error);
+              if (raw_exif_data)
                 {
-                  err = heif_context_add_exif_metadata (context, handle,
-                                                        exif_buffer, exif_size);
-                  if (err.code != 0)
+                  gsize exif_size = 0;
+                  gconstpointer exif_buffer = g_bytes_get_data (raw_exif_data, &exif_size);
+
+                  if (exif_size >= 4)
                     {
-                      g_printerr ("Failed to save EXIF metadata: %s", err.message);
+                      err = heif_context_add_exif_metadata (context, handle,
+                                                            exif_buffer, exif_size);
+                      if (err.code != 0)
+                        {
+                          g_printerr ("Failed to save EXIF metadata: %s", err.message);
+                        }
                     }
+                  g_bytes_unref (raw_exif_data);
                 }
-              g_bytes_unref (raw_exif_data);
-            }
-          else
-            {
-              if (error && *error)
+              else
                 {
-                  g_printerr ("%s: error preparing EXIF metadata: %s",
-                              G_STRFUNC, (*error)->message);
-                  g_clear_error (error);
+                  if (error && *error)
+                    {
+                      g_printerr ("%s: error preparing EXIF metadata: %s",
+                                  G_STRFUNC, (*error)->message);
+                      g_clear_error (error);
+                    }
                 }
             }
 
-          g_object_unref (new_exif_metadata);
-        }
-    }
-
-  /*  XMP metadata  */
-  if (save_xmp && metadata)
-    {
-      if (gexiv2_metadata_get_supports_xmp (GEXIV2_METADATA (metadata)) &&
-          gexiv2_metadata_has_xmp (GEXIV2_METADATA (metadata)))
-        {
-          GimpMetadata   *new_metadata = gimp_metadata_new ();
-          GExiv2Metadata *new_g2metadata = GEXIV2_METADATA (new_metadata);
-          guint           i;
-
-          static const XmpStructs structlist[] =
-          {
-            { "Xmp.iptcExt.LocationCreated", GEXIV2_STRUCTURE_XA_BAG },
-            { "Xmp.iptcExt.LocationShown",   GEXIV2_STRUCTURE_XA_BAG },
-            { "Xmp.iptcExt.ArtworkOrObject", GEXIV2_STRUCTURE_XA_BAG },
-            { "Xmp.iptcExt.RegistryId",      GEXIV2_STRUCTURE_XA_BAG },
-            { "Xmp.xmpMM.History",           GEXIV2_STRUCTURE_XA_SEQ },
-            { "Xmp.plus.ImageSupplier",      GEXIV2_STRUCTURE_XA_SEQ },
-            { "Xmp.plus.ImageCreator",       GEXIV2_STRUCTURE_XA_SEQ },
-            { "Xmp.plus.CopyrightOwner",     GEXIV2_STRUCTURE_XA_SEQ },
-            { "Xmp.plus.Licensor",           GEXIV2_STRUCTURE_XA_SEQ }
-          };
-
-          gchar         **xmp_data;
-          struct timeval  timer_usec;
-          gint64          timestamp_usec;
-          gchar           ts[128];
-          gchar          *xmp_packet;
-
-          gexiv2_metadata_clear_xmp (new_g2metadata);
-
-          gettimeofday (&timer_usec, NULL);
-          timestamp_usec = ( (gint64) timer_usec.tv_sec) * 1000000ll +
-                             (gint64) timer_usec.tv_usec;
-          g_snprintf (ts, sizeof (ts), "%" G_GINT64_FORMAT, timestamp_usec);
-
-          gimp_metadata_add_xmp_history (metadata, "");
-
-          gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
-                                              "Xmp.GIMP.TimeStamp",
-                                              ts,
-                                              NULL);
-
-          gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
-                                              "Xmp.xmp.CreatorTool",
-                                              "GIMP",
-                                              NULL);
-
-          gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
-                                              "Xmp.GIMP.Version",
-                                              GIMP_VERSION,
-                                              NULL);
-
-          gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
-                                              "Xmp.GIMP.API",
-                                              GIMP_API_VERSION,
-                                              NULL);
-
-          gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
-                                              "Xmp.GIMP.Platform",
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
-                                              "Windows",
-#elif defined(__linux__)
-                                              "Linux",
-#elif defined(__APPLE__) && defined(__MACH__)
-                                              "Mac OS",
-#elif defined(unix) || defined(__unix__) || defined(__unix)
-                                              "Unix",
-#else
-                                              "Unknown",
-#endif
-                                              NULL);
-
-
-          xmp_data = gexiv2_metadata_get_xmp_tags (GEXIV2_METADATA (metadata));
-
-          /* Patch necessary structures */
-          for (i = 0; i < (gint) G_N_ELEMENTS (structlist); i++)
-            {
-              gexiv2_metadata_try_set_xmp_tag_struct (GEXIV2_METADATA (new_g2metadata),
-                                                      structlist[i].tag,
-                                                      structlist[i].type,
-                                                      NULL);
-            }
-
-          for (i = 0; xmp_data[i] != NULL; i++)
+          /*  XMP metadata  */
+          if (save_xmp && gexiv2_metadata_has_xmp (filtered_g2metadata))
             {
-              if (! gexiv2_metadata_has_tag (new_g2metadata, xmp_data[i]) &&
-                  gimp_metadata_is_tag_supported (xmp_data[i], "image/heif"))
-                {
-                  heifplugin_image_metadata_copy_tag (GEXIV2_METADATA (metadata),
-                                                      new_g2metadata,
-                                                      xmp_data[i]);
-                }
-            }
+              gchar *xmp_packet;
 
-          g_strfreev (xmp_data);
-
-          xmp_packet = gexiv2_metadata_try_generate_xmp_packet (new_g2metadata, GEXIV2_USE_COMPACT_FORMAT | 
GEXIV2_OMIT_ALL_FORMATTING, 0, NULL);
-          if (xmp_packet)
-            {
-              int xmp_size = strlen (xmp_packet);
-              if (xmp_size > 0)
+              xmp_packet = gexiv2_metadata_try_generate_xmp_packet (filtered_g2metadata, 
GEXIV2_USE_COMPACT_FORMAT | GEXIV2_OMIT_ALL_FORMATTING, 0, NULL);
+              if (xmp_packet)
                 {
-                  heif_context_add_XMP_metadata (context, handle,
-                                                 xmp_packet, xmp_size);
+                  int xmp_size = strlen (xmp_packet);
+                  if (xmp_size > 0)
+                    {
+                      heif_context_add_XMP_metadata (context, handle,
+                                                     xmp_packet, xmp_size);
+                    }
+                  g_free (xmp_packet);
                 }
-              g_free (xmp_packet);
             }
 
-          g_object_unref (new_metadata);
+          g_object_unref (filtered_metadata);
         }
     }
 


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