/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * pikasaveprocedure.c * Copyright (C) 2019 Michael Natterer * * 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 . */ #include "config.h" #include "pika.h" #include "libpikabase/pikawire.h" /* FIXME kill this include */ #include "pikapdb_pdb.h" #include "pikaplugin-private.h" #include "pikasaveprocedure.h" #include "pikaprocedureconfig-private.h" #include "libpika-intl.h" enum { PROP_0, PROP_SUPPORTS_EXIF, PROP_SUPPORTS_IPTC, PROP_SUPPORTS_XMP, PROP_SUPPORTS_PROFILE, PROP_SUPPORTS_THUMBNAIL, PROP_SUPPORTS_COMMENT, N_PROPS }; struct _PikaSaveProcedurePrivate { PikaRunSaveFunc run_func; gpointer run_data; GDestroyNotify run_data_destroy; gboolean supports_exif; gboolean supports_iptc; gboolean supports_xmp; gboolean supports_profile; gboolean supports_thumbnail; gboolean supports_comment; gboolean export_metadata; }; static void pika_save_procedure_constructed (GObject *object); static void pika_save_procedure_finalize (GObject *object); static void pika_save_procedure_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void pika_save_procedure_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void pika_save_procedure_install (PikaProcedure *procedure); static PikaValueArray * pika_save_procedure_run (PikaProcedure *procedure, const PikaValueArray *args); static PikaProcedureConfig * pika_save_procedure_create_config (PikaProcedure *procedure, GParamSpec **args, gint n_args); static void pika_save_procedure_add_metadata (PikaSaveProcedure *save_procedure); G_DEFINE_TYPE_WITH_PRIVATE (PikaSaveProcedure, pika_save_procedure, PIKA_TYPE_FILE_PROCEDURE) #define parent_class pika_save_procedure_parent_class static GParamSpec *props[N_PROPS] = { NULL, }; static void pika_save_procedure_class_init (PikaSaveProcedureClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); PikaProcedureClass *procedure_class = PIKA_PROCEDURE_CLASS (klass); object_class->constructed = pika_save_procedure_constructed; object_class->finalize = pika_save_procedure_finalize; object_class->get_property = pika_save_procedure_get_property; object_class->set_property = pika_save_procedure_set_property; procedure_class->install = pika_save_procedure_install; procedure_class->run = pika_save_procedure_run; procedure_class->create_config = pika_save_procedure_create_config; /** * PikaSaveProcedure:supports-exif: * * Whether the save procedure supports EXIF. * * Since: 3.0.0 */ props[PROP_SUPPORTS_EXIF] = g_param_spec_boolean ("supports-exif", "Supports EXIF metadata storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); /** * PikaSaveProcedure:supports-iptc: * * Whether the save procedure supports IPTC. * * Since: 3.0.0 */ props[PROP_SUPPORTS_IPTC] = g_param_spec_boolean ("supports-iptc", "Supports IPTC metadata storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); /** * PikaSaveProcedure:supports-xmp: * * Whether the save procedure supports XMP. * * Since: 3.0.0 */ props[PROP_SUPPORTS_XMP] = g_param_spec_boolean ("supports-xmp", "Supports XMP metadata storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); /** * PikaSaveProcedure:supports-profile: * * Whether the save procedure supports ICC color profiles. * * Since: 3.0.0 */ props[PROP_SUPPORTS_PROFILE] = g_param_spec_boolean ("supports-profile", "Supports color profile storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); /** * PikaSaveProcedure:supports-thumbnail: * * Whether the save procedure supports storing a thumbnail. * * Since: 3.0.0 */ props[PROP_SUPPORTS_THUMBNAIL] = g_param_spec_boolean ("supports-thumbnail", "Supports thumbnail storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); /** * PikaSaveProcedure:supports-comment: * * Whether the save procedure supports storing a comment. * * Since: 3.0.0 */ props[PROP_SUPPORTS_COMMENT] = g_param_spec_boolean ("supports-comment", "Supports comment storage", NULL, FALSE, G_PARAM_CONSTRUCT | PIKA_PARAM_READWRITE); g_object_class_install_properties (object_class, N_PROPS, props); } static void pika_save_procedure_init (PikaSaveProcedure *procedure) { procedure->priv = pika_save_procedure_get_instance_private (procedure); procedure->priv->export_metadata = FALSE; } static void pika_save_procedure_constructed (GObject *object) { PikaProcedure *procedure = PIKA_PROCEDURE (object); G_OBJECT_CLASS (parent_class)->constructed (object); PIKA_PROC_ARG_IMAGE (procedure, "image", "Image", "The image to save", FALSE, G_PARAM_READWRITE); PIKA_PROC_ARG_INT (procedure, "num-drawables", "Number of drawables", "Number of drawables to be saved", 0, G_MAXINT, 1, G_PARAM_READWRITE); PIKA_PROC_ARG_OBJECT_ARRAY (procedure, "drawables", "Drawables", "The drawables to save", PIKA_TYPE_DRAWABLE, G_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE); PIKA_PROC_ARG_FILE (procedure, "file", "File", "The file to save to", PIKA_PARAM_READWRITE); } static void pika_save_procedure_finalize (GObject *object) { PikaSaveProcedure *procedure = PIKA_SAVE_PROCEDURE (object); if (procedure->priv->run_data_destroy) procedure->priv->run_data_destroy (procedure->priv->run_data); G_OBJECT_CLASS (parent_class)->finalize (object); } static void pika_save_procedure_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaSaveProcedure *procedure = PIKA_SAVE_PROCEDURE (object); switch (property_id) { case PROP_SUPPORTS_EXIF: procedure->priv->supports_exif = g_value_get_boolean (value); break; case PROP_SUPPORTS_IPTC: procedure->priv->supports_iptc = g_value_get_boolean (value); break; case PROP_SUPPORTS_XMP: procedure->priv->supports_xmp = g_value_get_boolean (value); break; case PROP_SUPPORTS_PROFILE: procedure->priv->supports_profile = g_value_get_boolean (value); break; case PROP_SUPPORTS_THUMBNAIL: procedure->priv->supports_thumbnail = g_value_get_boolean (value); break; case PROP_SUPPORTS_COMMENT: procedure->priv->supports_comment = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_save_procedure_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PikaSaveProcedure *procedure = PIKA_SAVE_PROCEDURE (object); switch (property_id) { case PROP_SUPPORTS_EXIF: g_value_set_boolean (value, procedure->priv->supports_exif); break; case PROP_SUPPORTS_IPTC: g_value_set_boolean (value, procedure->priv->supports_iptc); break; case PROP_SUPPORTS_XMP: g_value_set_boolean (value, procedure->priv->supports_xmp); break; case PROP_SUPPORTS_PROFILE: g_value_set_boolean (value, procedure->priv->supports_profile); break; case PROP_SUPPORTS_THUMBNAIL: g_value_set_boolean (value, procedure->priv->supports_thumbnail); break; case PROP_SUPPORTS_COMMENT: g_value_set_boolean (value, procedure->priv->supports_comment); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_save_procedure_install (PikaProcedure *procedure) { PikaFileProcedure *file_proc = PIKA_FILE_PROCEDURE (procedure); const gchar *mime_types; gint priority; pika_save_procedure_add_metadata (PIKA_SAVE_PROCEDURE (procedure)); PIKA_PROCEDURE_CLASS (parent_class)->install (procedure); _pika_pdb_set_file_proc_save_handler (pika_procedure_get_name (procedure), pika_file_procedure_get_extensions (file_proc), pika_file_procedure_get_prefixes (file_proc)); if (pika_file_procedure_get_handles_remote (file_proc)) _pika_pdb_set_file_proc_handles_remote (pika_procedure_get_name (procedure)); mime_types = pika_file_procedure_get_mime_types (file_proc); if (mime_types) _pika_pdb_set_file_proc_mime_types (pika_procedure_get_name (procedure), mime_types); priority = pika_file_procedure_get_priority (file_proc); if (priority != 0) _pika_pdb_set_file_proc_priority (pika_procedure_get_name (procedure), priority); } #define ARG_OFFSET 5 static PikaValueArray * pika_save_procedure_run (PikaProcedure *procedure, const PikaValueArray *args) { PikaPlugIn *plug_in; PikaSaveProcedure *save_proc = PIKA_SAVE_PROCEDURE (procedure); PikaValueArray *remaining; PikaValueArray *return_values; PikaProcedureConfig *config; PikaRunMode run_mode; PikaImage *image; PikaDrawable **drawables; GFile *file; gint n_drawables; PikaMetadata *metadata; gchar *mimetype = NULL; PikaPDBStatusType status = PIKA_PDB_EXECUTION_ERROR; run_mode = PIKA_VALUES_GET_ENUM (args, 0); image = PIKA_VALUES_GET_IMAGE (args, 1); n_drawables = PIKA_VALUES_GET_INT (args, 2); drawables = PIKA_VALUES_GET_OBJECT_ARRAY (args, 3); file = PIKA_VALUES_GET_FILE (args, 4); remaining = pika_value_array_new (pika_value_array_length (args) - ARG_OFFSET); for (gint i = ARG_OFFSET; i < pika_value_array_length (args); i++) { GValue *value = pika_value_array_index (args, i); pika_value_array_append (remaining, value); } config = pika_procedure_create_config (procedure); if (save_proc->priv->export_metadata) { mimetype = (gchar *) pika_file_procedure_get_mime_types (PIKA_FILE_PROCEDURE (procedure)); if (mimetype == NULL) { g_printerr ("%s: ERROR: the PikaSaveProcedureConfig object was created " "with export_metadata but you didn't set any MimeType with pika_file_procedure_set_mime_types()!\n", G_STRFUNC); } else { char *delim; mimetype = g_strdup (mimetype); mimetype = g_strstrip (mimetype); delim = strstr (mimetype, ","); if (delim) *delim = '\0'; /* Though docs only writes about the list being comma-separated, our * code apparently also split by spaces. */ delim = strstr (mimetype, " "); if (delim) *delim = '\0'; delim = strstr (mimetype, "\t"); if (delim) *delim = '\0'; } } metadata = _pika_procedure_config_begin_export (config, image, run_mode, remaining, mimetype); g_free (mimetype); return_values = save_proc->priv->run_func (procedure, run_mode, image, n_drawables, drawables, file, metadata, config, save_proc->priv->run_data); if (return_values != NULL && pika_value_array_length (return_values) > 0 && G_VALUE_HOLDS_ENUM (pika_value_array_index (return_values, 0))) status = PIKA_VALUES_GET_ENUM (return_values, 0); _pika_procedure_config_end_export (config, image, file, status); /* This is debug printing to help plug-in developers figure out best * practices. */ plug_in = pika_procedure_get_plug_in (procedure); if (G_OBJECT (config)->ref_count > 1 && _pika_plug_in_manage_memory_manually (plug_in)) g_printerr ("%s: ERROR: the PikaSaveProcedureConfig object was refed " "by plug-in, it MUST NOT do that!\n", G_STRFUNC); g_object_unref (config); pika_value_array_unref (remaining); return return_values; } static PikaProcedureConfig * pika_save_procedure_create_config (PikaProcedure *procedure, GParamSpec **args, gint n_args) { pika_save_procedure_add_metadata (PIKA_SAVE_PROCEDURE (procedure)); if (n_args > ARG_OFFSET) { args += ARG_OFFSET; n_args -= ARG_OFFSET; } else { args = NULL; n_args = 0; } return PIKA_PROCEDURE_CLASS (parent_class)->create_config (procedure, args, n_args); } static void pika_save_procedure_add_metadata (PikaSaveProcedure *save_procedure) { PikaProcedure *procedure = PIKA_PROCEDURE (save_procedure); static gboolean ran_once = FALSE; if (ran_once) return; if (save_procedure->priv->supports_exif) PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-exif", _("Save _Exif"), _("Save Exif (Exchangeable image file format) metadata"), pika_export_exif (), G_PARAM_READWRITE); if (save_procedure->priv->supports_iptc) PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-iptc", _("Save _IPTC"), _("Save IPTC (International Press Telecommunications Council) metadata"), pika_export_iptc (), G_PARAM_READWRITE); if (save_procedure->priv->supports_xmp) PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-xmp", _("Save _XMP"), _("Save XMP (Extensible Metadata Platform) metadata"), pika_export_xmp (), G_PARAM_READWRITE); if (save_procedure->priv->supports_profile) PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-color-profile", _("Save color _profile"), _("Save the ICC color profile as metadata"), pika_export_color_profile (), G_PARAM_READWRITE); if (save_procedure->priv->supports_thumbnail) PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-thumbnail", _("Save _thumbnail"), _("Save a smaller representation of the image as metadata"), pika_export_thumbnail (), G_PARAM_READWRITE); if (save_procedure->priv->supports_comment) { PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "save-comment", _("Save c_omment"), _("Save a comment as metadata"), pika_export_comment (), G_PARAM_READWRITE); PIKA_PROC_AUX_ARG_STRING (procedure, "pika-comment", _("Comment"), _("Image comment"), pika_get_default_comment (), G_PARAM_READWRITE); pika_procedure_set_argument_sync (procedure, "pika-comment", PIKA_ARGUMENT_SYNC_PARASITE); } ran_once = TRUE; } /* public functions */ /** * pika_save_procedure_new: * @plug_in: a #PikaPlugIn. * @name: the new procedure's name. * @proc_type: the new procedure's #PikaPDBProcType. * @export_metadata: whether PIKA should handle metadata exporting. * @run_func: the run function for the new procedure. * @run_data: user data passed to @run_func. * @run_data_destroy: (nullable): free function for @run_data, or %NULL. * * Creates a new save procedure named @name which will call @run_func * when invoked. * * See pika_procedure_new() for information about @proc_type. * * #PikaSaveProcedure is a #PikaProcedure subclass that makes it easier * to write file save procedures. * * It automatically adds the standard * * (#PikaRunMode, #PikaImage, #PikaDrawable, #GFile) * * arguments of a save procedure. It is possible to add additional * arguments. * * When invoked via pika_procedure_run(), it unpacks these standard * arguments and calls @run_func which is a #PikaRunSaveFunc. The * #PikaProcedureConfig of #PikaRunSaveFunc only contains additionally added * arguments. * * If @export_metadata is TRUE, then the class will also handle the metadata * export if the format is supported by our backend. This requires you to also * set appropriate MimeType with pika_file_procedure_set_mime_types(). * * Returns: a new #PikaProcedure. * * Since: 3.0 **/ PikaProcedure * pika_save_procedure_new (PikaPlugIn *plug_in, const gchar *name, PikaPDBProcType proc_type, gboolean export_metadata, PikaRunSaveFunc run_func, gpointer run_data, GDestroyNotify run_data_destroy) { PikaSaveProcedure *procedure; g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL); g_return_val_if_fail (pika_is_canonical_identifier (name), NULL); g_return_val_if_fail (proc_type != PIKA_PDB_PROC_TYPE_INTERNAL, NULL); g_return_val_if_fail (proc_type != PIKA_PDB_PROC_TYPE_EXTENSION, NULL); g_return_val_if_fail (run_func != NULL, NULL); procedure = g_object_new (PIKA_TYPE_SAVE_PROCEDURE, "plug-in", plug_in, "name", name, "procedure-type", proc_type, NULL); procedure->priv->run_func = run_func; procedure->priv->export_metadata = export_metadata; procedure->priv->run_data = run_data; procedure->priv->run_data_destroy = run_data_destroy; return PIKA_PROCEDURE (procedure); } /** * pika_save_procedure_set_support_exif: * @procedure: a #PikaProcedure. * @supports: whether Exif metadata are supported. * * Determine whether @procedure supports saving Exif data. By default, * it won't (so there is usually no reason to run this function with * %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument "save-exif" in the * end of the argument list of @procedure, with relevant blurb and * description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be [func@export_exif]. * * Since: 3.0 **/ void pika_save_procedure_set_support_exif (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-exif", supports, NULL); } /** * pika_save_procedure_set_support_iptc: * @procedure: a #PikaProcedure. * @supports: whether IPTC metadata are supported. * * Determine whether @procedure supports saving IPTC data. By default, * it won't (so there is usually no reason to run this function with * %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument "save-iptc" in the * end of the argument list of @procedure, with relevant blurb and * description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be [func@export_iptc]. * * Since: 3.0 **/ void pika_save_procedure_set_support_iptc (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-iptc", supports, NULL); } /** * pika_save_procedure_set_support_xmp: * @procedure: a #PikaProcedure. * @supports: whether XMP metadata are supported. * * Determine whether @procedure supports saving XMP data. By default, * it won't (so there is usually no reason to run this function with * %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument "save-xmp" in the * end of the argument list of @procedure, with relevant blurb and * description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be [func@export_xmp]. * * Since: 3.0 **/ void pika_save_procedure_set_support_xmp (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-xmp", supports, NULL); } /** * pika_save_procedure_set_support_profile: * @procedure: a #PikaProcedure. * @supports: whether color profiles can be stored. * * Determine whether @procedure supports saving ICC color profiles. By * default, it won't (so there is usually no reason to run this function * with %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument * "save-color-profile" in the end of the argument list of @procedure, * with relevant blurb and description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be [func@export_color_profile]. * * Since: 3.0 **/ void pika_save_procedure_set_support_profile (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-profile", supports, NULL); } /** * pika_save_procedure_set_support_thumbnail: * @procedure: a #PikaProcedure. * @supports: whether a thumbnail can be stored. * * Determine whether @procedure supports saving a thumbnail. By default, * it won't (so there is usually no reason to run this function with * %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument "save-thumbnail" * in the end of the argument list of @procedure, with relevant blurb * and description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be * [func@export_thumbnail]. * * Since: 3.0 **/ void pika_save_procedure_set_support_thumbnail (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-thumbnail", supports, NULL); } /** * pika_save_procedure_set_support_comment: * @procedure: a #PikaProcedure. * @supports: whether a comment can be stored. * * Determine whether @procedure supports saving a comment. By default, * it won't (so there is usually no reason to run this function with * %FALSE). * * This will have several consequences: * * - Automatically adds a standard auxiliary argument "save-comment" * in the end of the argument list of @procedure, with relevant blurb * and description. * - If used with other pika_save_procedure_set_support_*() functions, * they will always be ordered the same (the order of the calls don't * matter), keeping all save procedures consistent. * - Generated PikaSaveProcedureDialog will contain the metadata * options, once again always in the same order and with consistent * GUI style across plug-ins. * - API from [class@ProcedureConfig] will automatically process these * properties to decide whether to save a given metadata or not. * * Note that since this is an auxiliary argument, it won't be part of * the PDB arguments. By default, the value will be * [func@export_comment]. * * Since: 3.0 **/ void pika_save_procedure_set_support_comment (PikaSaveProcedure *procedure, gboolean supports) { g_return_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure)); g_object_set (procedure, "supports-comment", supports, NULL); } /** * pika_save_procedure_get_support_exif: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports Exif saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_exif (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_exif; } /** * pika_save_procedure_get_support_iptc: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports IPTC saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_iptc (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_iptc; } /** * pika_save_procedure_get_support_xmp: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports XMP saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_xmp (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_xmp; } /** * pika_save_procedure_get_support_profile: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports ICC color profile saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_profile (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_profile; } /** * pika_save_procedure_get_support_thumbnail: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports thumbnail saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_thumbnail (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_thumbnail; } /** * pika_save_procedure_get_support_comment: * @procedure: a #PikaProcedure. * * Returns: %TRUE if @procedure supports comment saving. * * Since: 3.0 **/ gboolean pika_save_procedure_get_support_comment (PikaSaveProcedure *procedure) { g_return_val_if_fail (PIKA_IS_SAVE_PROCEDURE (procedure), FALSE); return procedure->priv->supports_comment; }