[gimp] plug-ins: refactor metadata saving in HEIF/AVIF plugin
- From: Daniel Novomeský <dnovomesky src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: refactor metadata saving in HEIF/AVIF plugin
- Date: Wed, 16 Mar 2022 17:01:26 +0000 (UTC)
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]