[gimp] Bug 769871 - Adds selection to save exif/xmp when exporting a webp file.
- From: Benoit Touchette <bentou src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 769871 - Adds selection to save exif/xmp when exporting a webp file.
- Date: Tue, 16 Aug 2016 20:55:11 +0000 (UTC)
commit 05e4c5fe28d9b7a054a09fee54d801fe150f115f
Author: Benoit Touchette <draekko software+gimp gmail com>
Date: Tue Aug 16 16:49:57 2016 -0400
Bug 769871 - Adds selection to save exif/xmp when exporting a webp file.
This adds an expander to the webp file plug-in to select whether
to save or not the exif, and xmp data for webp files. This harmonizes
the plug-in with a similar option to the jpg/png file plug-ins.
https://bugzilla.gnome.org/show_bug.cgi?id=769871
plug-ins/file-webp/file-webp-dialog.c | 56 +++-
plug-ins/file-webp/file-webp-save.c | 19 +
plug-ins/file-webp/file-webp-save.c.orig | 622 ++++++++++++++++++++++++++++++
plug-ins/file-webp/file-webp-save.h | 3 +
plug-ins/file-webp/file-webp.c | 11 +-
5 files changed, 709 insertions(+), 2 deletions(-)
---
diff --git a/plug-ins/file-webp/file-webp-dialog.c b/plug-ins/file-webp/file-webp-dialog.c
index 678a45f..6580e5a 100644
--- a/plug-ins/file-webp/file-webp-dialog.c
+++ b/plug-ins/file-webp/file-webp-dialog.c
@@ -52,7 +52,6 @@ static struct
{ 0 }
};
-
static GtkListStore *
save_dialog_presets (void)
{
@@ -97,6 +96,11 @@ save_dialog (WebPSaveParams *params,
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *table;
+ GtkWidget *expander;
+ GtkWidget *frame;
+ GtkWidget *table2;
+ GtkWidget *save_exif;
+ GtkWidget *save_xmp;
GtkWidget *preset_label;
GtkListStore *preset_list;
GtkWidget *preset_combo;
@@ -108,6 +112,7 @@ save_dialog (WebPSaveParams *params,
gboolean animation_supported = FALSE;
gint slider1 , slider2;
gboolean run;
+ gchar *text;
animation_supported = n_layers > 1;
@@ -251,6 +256,55 @@ save_dialog (WebPSaveParams *params,
G_CALLBACK (save_dialog_toggle_scale),
alpha_quality_scale);
+ text = g_strdup_printf ("<b>%s</b>", _("_Advanced Options"));
+ expander = gtk_expander_new_with_mnemonic (text);
+ gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
+ g_free (text);
+
+ gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
+ gtk_widget_show (expander);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_add (GTK_CONTAINER (expander), vbox);
+ gtk_widget_show (vbox);
+
+ frame = gimp_frame_new ("<expander>");
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ table2 = gtk_table_new (2, 1, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table2), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table2), 6);
+ gtk_table_set_col_spacing (GTK_TABLE (table2), 1, 12);
+ gtk_container_add (GTK_CONTAINER (frame), table2);
+
+ /* Save EXIF data */
+ save_exif = gtk_check_button_new_with_mnemonic (_("Save _Exif data"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (save_exif), params->exif);
+ gtk_widget_set_sensitive (save_exif, TRUE);
+ gtk_table_attach (GTK_TABLE (table2), save_exif, 0, 1,
+ 0, 1, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (save_exif);
+
+ g_signal_connect (save_exif, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ ¶ms->exif);
+
+ /* XMP metadata */
+ save_xmp = gtk_check_button_new_with_mnemonic (_("Save _XMP data"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (save_xmp), params->xmp);
+ gtk_table_attach (GTK_TABLE (table2), save_xmp, 0, 1,
+ 1, 2, GTK_FILL, 0, 0, 0);
+ gtk_widget_show (save_xmp);
+
+ g_signal_connect (save_xmp, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ ¶ms->xmp);
+
+ gtk_widget_set_sensitive (save_xmp, TRUE);
+
+ gtk_widget_show (table2);
+
gtk_widget_show (dialog);
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
diff --git a/plug-ins/file-webp/file-webp-save.c b/plug-ins/file-webp/file-webp-save.c
index 4f050e4..b7e380b 100644
--- a/plug-ins/file-webp/file-webp-save.c
+++ b/plug-ins/file-webp/file-webp-save.c
@@ -609,6 +609,25 @@ save_image (const gchar *filename,
if (metadata)
{
gimp_metadata_set_bits_per_sample (metadata, 8);
+
+ if (params->exif)
+ metadata_flags |= GIMP_METADATA_SAVE_EXIF;
+ else
+ metadata_flags &= ~GIMP_METADATA_SAVE_EXIF;
+
+ /* WebP doesn't support iptc natively and
+ sets it via xmp */
+ if (params->xmp)
+ {
+ metadata_flags |= GIMP_METADATA_SAVE_XMP;
+ metadata_flags |= GIMP_METADATA_SAVE_IPTC;
+ }
+ else
+ {
+ metadata_flags &= ~GIMP_METADATA_SAVE_XMP;
+ metadata_flags &= ~GIMP_METADATA_SAVE_IPTC;
+ }
+
file = g_file_new_for_path (filename);
gimp_image_metadata_save_finish (image_ID,
"image/webp",
diff --git a/plug-ins/file-webp/file-webp-save.c.orig b/plug-ins/file-webp/file-webp-save.c.orig
new file mode 100644
index 0000000..4f050e4
--- /dev/null
+++ b/plug-ins/file-webp/file-webp-save.c.orig
@@ -0,0 +1,622 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * file-webp - WebP file format plug-in for the GIMP
+ * Copyright (C) 2015 Nathan Osman
+ * Copyright (C) 2016 Ben Touchette
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <glib/gstdio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <gegl.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include <webp/encode.h>
+#include <webp/mux.h>
+
+#include "file-webp-save.h"
+
+#include "libgimp/stdplugins-intl.h"
+
+
+WebPPreset webp_preset_by_name (gchar *name);
+int webp_anim_file_writer (FILE *outfile,
+ const uint8_t *data,
+ size_t data_size);
+int webp_file_writer (const uint8_t *data,
+ size_t data_size,
+ const WebPPicture *picture);
+int webp_file_progress (int percent,
+ const WebPPicture *picture);
+const gchar * webp_error_string (WebPEncodingError error_code);
+
+gboolean save_layer (const gchar *filename,
+ gint32 nLayers,
+ gint32 image_ID,
+ gint32 drawable_ID,
+ WebPSaveParams *params,
+ GError **error);
+
+gboolean save_animation (const gchar *filename,
+ gint32 nLayers,
+ gint32 *allLayers,
+ gint32 image_ID,
+ gint32 drawable_ID,
+ WebPSaveParams *params,
+ GError **error);
+
+
+WebPPreset
+webp_preset_by_name (gchar *name)
+{
+ if( ! strcmp (name, "picture"))
+ {
+ return WEBP_PRESET_PICTURE;
+ }
+ else if (! strcmp (name, "photo"))
+ {
+ return WEBP_PRESET_PHOTO;
+ }
+ else if (! strcmp (name, "drawing"))
+ {
+ return WEBP_PRESET_DRAWING;
+ }
+ else if (! strcmp (name, "icon"))
+ {
+ return WEBP_PRESET_ICON;
+ }
+ else if (! strcmp (name, "text"))
+ {
+ return WEBP_PRESET_TEXT;
+ }
+ else
+ {
+ return WEBP_PRESET_DEFAULT;
+ }
+}
+
+int
+webp_anim_file_writer (FILE *outfile,
+ const uint8_t *data,
+ size_t data_size)
+{
+ int ok = 0;
+
+ if (data == NULL)
+ return 0;
+
+ ok = (fwrite (data, data_size, 1, outfile) == 1);
+
+ return ok;
+}
+
+int
+webp_file_writer (const uint8_t *data,
+ size_t data_size,
+ const WebPPicture *picture)
+{
+ FILE *outfile;
+
+ /* Obtain the FILE* and write the data to the file */
+ outfile = (FILE *) picture->custom_ptr;
+
+ return fwrite (data, sizeof (uint8_t), data_size, outfile) == data_size;
+}
+
+int
+webp_file_progress (int percent,
+ const WebPPicture *picture)
+{
+ return gimp_progress_update (percent / 100.0);
+}
+
+const gchar *
+webp_error_string (WebPEncodingError error_code)
+{
+ switch (error_code)
+ {
+ case VP8_ENC_ERROR_OUT_OF_MEMORY:
+ return _("out of memory");
+ case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
+ return _("not enough memory to flush bits");
+ case VP8_ENC_ERROR_NULL_PARAMETER:
+ return _("NULL parameter");
+ case VP8_ENC_ERROR_INVALID_CONFIGURATION:
+ return _("invalid configuration");
+ case VP8_ENC_ERROR_BAD_DIMENSION:
+ return _("bad image dimensions");
+ case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
+ return _("partition is bigger than 512K");
+ case VP8_ENC_ERROR_PARTITION_OVERFLOW:
+ return _("partition is bigger than 16M");
+ case VP8_ENC_ERROR_BAD_WRITE:
+ return _("unable to flush bytes");
+ case VP8_ENC_ERROR_FILE_TOO_BIG:
+ return _("file is larger than 4GiB");
+ case VP8_ENC_ERROR_USER_ABORT:
+ return _("user aborted encoding");
+ case VP8_ENC_ERROR_LAST:
+ return _("list terminator");
+ default:
+ return _("unknown error");
+ }
+}
+
+gboolean
+save_layer (const gchar *filename,
+ gint32 nLayers,
+ gint32 image_ID,
+ gint32 drawable_ID,
+ WebPSaveParams *params,
+ GError **error)
+{
+ gboolean status = FALSE;
+ FILE *outfile = NULL;
+ WebPConfig config = {0};
+ WebPPicture picture = {0};
+ guchar *buffer = NULL;
+ gint w, h;
+ gint bpp;
+ GimpColorProfile *profile;
+ GimpImageType drawable_type;
+ GeglBuffer *geglbuffer = NULL;
+ GeglRectangle extent;
+ gchar *indata;
+ gsize indatalen;
+ struct stat stsz;
+ int fd_outfile;
+ WebPData chunk;
+ int res;
+
+ /* The do...while() loop is a neat little trick that makes it easier
+ * to jump to error handling code while still ensuring proper
+ * cleanup
+ */
+
+ do
+ {
+ /* Begin displaying export progress */
+ gimp_progress_init_printf (_("Saving '%s'"),
+ gimp_filename_to_utf8(filename));
+
+ /* Attempt to open the output file */
+ if ((outfile = g_fopen (filename, "wb+")) == NULL)
+ {
+ g_set_error (error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Unable to open '%s' for writing"),
+ gimp_filename_to_utf8 (filename));
+ break;
+ }
+
+ /* Obtain the drawable type */
+ drawable_type = gimp_drawable_type (drawable_ID);
+
+ /* Retrieve the buffer for the layer */
+ geglbuffer = gimp_drawable_get_buffer (drawable_ID);
+ extent = *gegl_buffer_get_extent (geglbuffer);
+ bpp = gimp_drawable_bpp (drawable_ID);
+ w = extent.width;
+ h = extent.height;
+
+ /* Initialize the WebP configuration with a preset and fill in the
+ * remaining values */
+ WebPConfigPreset (&config,
+ webp_preset_by_name (params->preset),
+ params->quality);
+
+ config.lossless = params->lossless;
+ config.method = 6; /* better quality */
+ config.alpha_quality = params->alpha_quality;
+
+ /* Prepare the WebP structure */
+ WebPPictureInit (&picture);
+ picture.use_argb = 1;
+ picture.width = w;
+ picture.height = h;
+ picture.writer = webp_file_writer;
+ picture.custom_ptr = outfile;
+ picture.progress_hook = webp_file_progress;
+
+ /* Attempt to allocate a buffer of the appropriate size */
+ buffer = (guchar *) g_malloc (w * h * bpp);
+ if(! buffer)
+ break;
+
+ /* Read the region into the buffer */
+ gegl_buffer_get (geglbuffer, &extent, 1.0, NULL, buffer,
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+ /* Use the appropriate function to import the data from the buffer */
+ if (drawable_type == GIMP_RGB_IMAGE)
+ {
+ WebPPictureImportRGB (&picture, buffer, w * bpp);
+ }
+ else
+ {
+ WebPPictureImportRGBA (&picture, buffer, w * bpp);
+ }
+
+ /* Perform the actual encode */
+ if (! WebPEncode (&config, &picture))
+ {
+ g_printerr ("WebP error: '%s'",
+ webp_error_string (picture.error_code));
+ g_set_error (error, G_FILE_ERROR,
+ picture.error_code,
+ _("WebP error: '%s'"),
+ webp_error_string (picture.error_code));
+ break;
+ }
+
+ /* The cleanup stuff still needs to run but indicate that everything
+ * completed successfully
+ */
+ status = TRUE;
+
+ }
+ while (0);
+
+ /* Flush the drawable and detach */
+ if (geglbuffer)
+ {
+ gegl_buffer_flush (geglbuffer);
+ g_object_unref (geglbuffer);
+ }
+
+ fflush (outfile);
+ fd_outfile = fileno (outfile);
+ fstat (fd_outfile, &stsz);
+ indatalen = stsz.st_size;
+ if (indatalen > 0)
+ {
+ indata = (gchar*) g_malloc (indatalen);
+ rewind (outfile);
+ res = fread (indata, 1, indatalen, outfile);
+ if (res > 0)
+ {
+ WebPMux *mux;
+ WebPData wp_data;
+
+ wp_data.bytes = (uint8_t*) indata;
+ wp_data.size = indatalen;
+ mux = WebPMuxCreate (&wp_data, 1);
+
+ if (mux)
+ {
+ gboolean saved = FALSE;
+
+ /* Save ICC data */
+ profile = gimp_image_get_color_profile (image_ID);
+ if (profile)
+ {
+ const guint8 *icc_data;
+ gsize icc_data_size;
+
+ saved = TRUE;
+
+ icc_data = gimp_color_profile_get_icc_profile (profile,
+ &icc_data_size);
+ chunk.bytes = icc_data;
+ chunk.size = icc_data_size;
+ WebPMuxSetChunk(mux, "ICCP", &chunk, 1);
+ g_object_unref (profile);
+ }
+
+ if (saved == TRUE)
+ {
+ WebPMuxAssemble (mux, &wp_data);
+ rewind (outfile);
+ webp_anim_file_writer (outfile, wp_data.bytes, wp_data.size);
+ }
+ }
+ else
+ {
+ g_printerr ("ERROR: Cannot create mux. Can't save features update.\n");
+ }
+
+ WebPDataClear (&wp_data);
+ }
+ else
+ {
+ g_printerr ("ERROR: No data read for features. Can't save features update.\n");
+ }
+ }
+ else
+ {
+ g_printerr ("ERROR: No data for features. Can't save features update.\n");
+ }
+
+ /* Free any resources */
+ if (outfile)
+ fclose (outfile);
+
+ if (buffer)
+ free (buffer);
+
+ WebPPictureFree (&picture);
+
+ return status;
+}
+
+gboolean
+save_animation (const gchar *filename,
+ gint32 nLayers,
+ gint32 *allLayers,
+ gint32 image_ID,
+ gint32 drawable_ID,
+ WebPSaveParams *params,
+ GError **error)
+{
+ gboolean status = FALSE;
+ FILE *outfile = NULL;
+ guchar *buffer = NULL;
+ gint w, h, bpp;
+ GimpImageType drawable_type;
+ GimpColorProfile *profile;
+ WebPAnimEncoderOptions enc_options;
+ WebPData webp_data;
+ int frame_timestamp = 0;
+ WebPAnimEncoder *enc;
+ WebPMux *mux;
+ WebPMuxAnimParams anim_params = {0};
+
+ if (nLayers < 1)
+ return FALSE;
+
+ gimp_image_undo_freeze (image_ID);
+
+ do
+ {
+ gint loop;
+
+ /* Begin displaying export progress */
+ gimp_progress_init_printf (_("Saving '%s'"),
+ gimp_filename_to_utf8 (filename));
+
+ /* Attempt to open the output file */
+ if ((outfile = g_fopen (filename, "wb")) == NULL)
+ {
+ g_set_error (error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Unable to open '%s' for writing"),
+ gimp_filename_to_utf8 (filename));
+ break;
+ }
+
+ WebPDataInit (&webp_data);
+ if (! WebPAnimEncoderOptionsInit (&enc_options))
+ {
+ g_printerr ("ERROR: verion mismatch\n");
+ break;
+ }
+
+ for (loop = 0; loop < nLayers; loop++)
+ {
+ GeglBuffer *geglbuffer;
+ GeglRectangle extent;
+ WebPConfig config;
+ WebPPicture picture;
+ WebPMemoryWriter mw = { 0 };
+
+ /* Obtain the drawable type */
+ drawable_type = gimp_drawable_type (allLayers[loop]);
+
+ /* fix layers to avoid offset errors */
+ gimp_layer_resize_to_image_size (allLayers[loop]);
+
+ /* Retrieve the buffer for the layer */
+ geglbuffer = gimp_drawable_get_buffer (allLayers[loop]);
+ extent = *gegl_buffer_get_extent (geglbuffer);
+ bpp = gimp_drawable_bpp (allLayers[loop]);
+ w = extent.width;
+ h = extent.height;
+
+ if (loop == 0)
+ {
+ enc = WebPAnimEncoderNew (w, h, &enc_options);
+ if (! enc)
+ {
+ g_printerr ("ERROR: enc == null\n");
+ break;
+ }
+ }
+
+ /* Attempt to allocate a buffer of the appropriate size */
+ buffer = (guchar *) g_malloc (w * h * bpp);
+ if(! buffer)
+ {
+ g_printerr ("Buffer error: 'buffer null'\n");
+ status = FALSE;
+ break;
+ }
+
+ WebPConfigInit (&config);
+ WebPConfigPreset (&config,
+ webp_preset_by_name (params->preset),
+ params->quality);
+
+ config.lossless = params->lossless;
+ config.method = 6; /* better quality */
+ config.alpha_quality = params->alpha_quality;
+ config.exact = 1;
+
+ WebPMemoryWriterInit (&mw);
+
+ /* Prepare the WebP structure */
+ WebPPictureInit (&picture);
+ picture.use_argb = 1;
+ picture.argb_stride = w * bpp;
+ picture.width = w;
+ picture.height = h;
+ picture.custom_ptr = &mw;
+ picture.writer = WebPMemoryWrite;
+ picture.progress_hook = webp_file_progress;
+
+ /* Read the region into the buffer */
+ gegl_buffer_get (geglbuffer, &extent, 1.0, NULL, buffer,
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+ /* Use the appropriate function to import the data from the buffer */
+ if (drawable_type == GIMP_RGB_IMAGE)
+ {
+ WebPPictureImportRGB (&picture, buffer, w * bpp);
+ }
+ else
+ {
+ WebPPictureImportRGBA (&picture, buffer, w * bpp);
+ }
+
+ /* Perform the actual encode */
+ if (! WebPAnimEncoderAdd (enc, &picture, frame_timestamp, &config))
+ {
+ g_printerr ("ERROR[%d]: %s\n",
+ picture.error_code,
+ webp_error_string (picture.error_code));
+ }
+
+ WebPMemoryWriterClear (&mw);
+ WebPPictureFree (&picture);
+
+ if (buffer)
+ free (buffer);
+
+ /* Flush the drawable and detach */
+ gegl_buffer_flush (geglbuffer);
+ g_object_unref (geglbuffer);
+ }
+
+ WebPAnimEncoderAdd (enc, NULL, frame_timestamp, NULL);
+
+ if (! WebPAnimEncoderAssemble (enc, &webp_data))
+ {
+ g_printerr ("ERROR: %s\n",
+ WebPAnimEncoderGetError (enc));
+ }
+
+ /* Set animations parameters */
+ mux = WebPMuxCreate (&webp_data, 1);
+
+ anim_params.loop_count = 0;
+ if (params->loop == FALSE)
+ {
+ anim_params.loop_count = 1;
+ }
+
+ WebPMuxSetAnimationParams (mux, &anim_params);
+
+ /* Save ICC data */
+ profile = gimp_image_get_color_profile (image_ID);
+ if (profile)
+ {
+ WebPData chunk;
+ const guint8 *icc_data;
+ gsize icc_data_size;
+
+ icc_data = gimp_color_profile_get_icc_profile (profile, &icc_data_size);
+ chunk.bytes = icc_data;
+ chunk.size = icc_data_size;
+ WebPMuxSetChunk (mux, "ICCP", &chunk, 1);
+ g_object_unref (profile);
+ }
+
+ WebPMuxAssemble (mux, &webp_data);
+
+ webp_anim_file_writer (outfile, webp_data.bytes, webp_data.size);
+
+ WebPDataClear (&webp_data);
+ WebPAnimEncoderDelete (enc);
+
+ status = TRUE;
+ }
+ while (0);
+
+ /* Free any resources */
+ if (outfile)
+ fclose (outfile);
+
+ return status;
+}
+
+
+gboolean
+save_image (const gchar *filename,
+ gint32 nLayers,
+ gint32 *allLayers,
+ gint32 image_ID,
+ gint32 drawable_ID,
+ WebPSaveParams *params,
+ GError **error)
+{
+ GimpMetadata *metadata;
+ GimpMetadataSaveFlags metadata_flags;
+ gboolean status = FALSE;
+ GFile *file;
+
+ if (nLayers == 0)
+ return FALSE;
+
+ g_printerr("Saving WebP file %s\n", filename);
+
+ if (nLayers == 1)
+ {
+ status = save_layer (filename, nLayers, image_ID, drawable_ID, params,
+ error);
+ }
+ else
+ {
+ if (! params->animation)
+ {
+ status = save_layer (filename,
+ nLayers, image_ID, drawable_ID, params,
+ error);
+ }
+ else
+ {
+ status = save_animation (filename,
+ nLayers, allLayers, image_ID, drawable_ID,
+ params, error);
+ }
+ }
+
+ metadata = gimp_image_metadata_save_prepare (image_ID,
+ "image/webp",
+ &metadata_flags);
+
+ if (metadata)
+ {
+ gimp_metadata_set_bits_per_sample (metadata, 8);
+ file = g_file_new_for_path (filename);
+ gimp_image_metadata_save_finish (image_ID,
+ "image/webp",
+ metadata, metadata_flags,
+ file, NULL);
+ g_object_unref (file);
+ }
+
+ /* Return the status */
+ return status;
+}
diff --git a/plug-ins/file-webp/file-webp-save.h b/plug-ins/file-webp/file-webp-save.h
index 643ccf8..98fb202 100644
--- a/plug-ins/file-webp/file-webp-save.h
+++ b/plug-ins/file-webp/file-webp-save.h
@@ -31,6 +31,9 @@ typedef struct
gboolean loop;
gfloat quality;
gfloat alpha_quality;
+ gboolean exif;
+ gboolean iptc;
+ gboolean xmp;
} WebPSaveParams;
diff --git a/plug-ins/file-webp/file-webp.c b/plug-ins/file-webp/file-webp.c
index b845525..0a8a9db 100644
--- a/plug-ins/file-webp/file-webp.c
+++ b/plug-ins/file-webp/file-webp.c
@@ -87,7 +87,10 @@ query (void)
{ GIMP_PDB_FLOAT, "quality", "Quality of the image (0 <= quality <= 100)" },
{ GIMP_PDB_FLOAT, "alpha-quality", "Quality of the image's alpha channel (0 <= alpha-quality <= 100)"
},
{ GIMP_PDB_INT32, "animation", "Use layers for animation (0/1)" },
- { GIMP_PDB_INT32, "anim-loop", "Loop animation infinitely (0/1)" }
+ { GIMP_PDB_INT32, "anim-loop", "Loop animation infinitely (0/1)" },
+ { GIMP_PDB_INT32, "exif", "Toggle saving exif data (0/1)" },
+ { GIMP_PDB_INT32, "iptc", "Toggle saving iptc data (0/1)" },
+ { GIMP_PDB_INT32, "xmp", "Toggle saving xmp data (0/1)" }
};
gimp_install_procedure (LOAD_PROCEDURE,
@@ -187,6 +190,9 @@ run (const gchar *name,
params.loop = TRUE;
params.quality = 90.0f;
params.alpha_quality = 100.0f;
+ params.exif = TRUE;
+ params.iptc = TRUE;
+ params.xmp = TRUE;
/* Load the image and drawable IDs */
image_ID = param[1].data.d_int32;
@@ -238,6 +244,9 @@ run (const gchar *name,
params.alpha_quality = param[8].data.d_float;
params.animation = param[9].data.d_int32;
params.loop = param[10].data.d_int32;
+ params.exif = param[11].data.d_int32;
+ params.iptc = param[12].data.d_int32;
+ params.xmp = param[13].data.d_int32;
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]