mirror of https://github.com/GNOME/gimp.git
app, libgimp, plug-ins: move Orientation metadata handling into core.
Orientation is now handled by core code, just next to profile conversion handling. One of the first consequence is that we don't need to have a non-GUI version gimp_image_metadata_load_finish_batch() in libgimp, next to a GUI version of the gimp_image_metadata_load_finish() function in libgimpui. This makes for simpler API. Also a plug-in which wishes to get access to the rotation dialog provided by GIMP without loading ligimpui/GTK+ (for whatever reason) will still have the feature. The main advantage is that the "Don't ask me again" feature is now handled by a settings in `Preferences > Image Import & Export` as the "Metadata rotation policy". Until now it was saved as a global parasite, which made it virtually non-editable once you checked it once (no easy way to edit parasites except by scripts). So say you refused the rotation once while checking "Don't ask again", and GIMP will forever discard the rotation metadata without giving you a sane way to change your mind. Of course, I could have passed the settings to plug-ins through the PDB, but I find it a lot better to simply handle such settings core-side. The dialog code is basically the same as an app/dialogs/ as it was in libgimp, with the minor improvement that it now takes the scale ratio into account (basically the maximum thumbnail size will be bigger on higher density displays). Only downside of the move to the core is that this rotation dialog is raised only when you open an image from the core, not as a PDB call. So a plug-in which makes say a "file-jpeg-load" PDB call, even in INTERACTIVE run mode, won't have rotation processed. Note that this was already the same for embedded color profile conversion. This can be wanted or not. Anyway some additional libgimp calls might be of interest to explicitly call the core dialogs.
This commit is contained in:
parent
5fb0577768
commit
67e2e1b5bb
|
@ -47,6 +47,7 @@ enum
|
|||
PROP_GIMP,
|
||||
|
||||
PROP_COLOR_PROFILE_POLICY,
|
||||
PROP_METADATA_ROTATION_POLICY,
|
||||
|
||||
PROP_COLOR_PROFILE_PATH,
|
||||
|
||||
|
@ -176,6 +177,14 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass)
|
|||
GIMP_COLOR_PROFILE_POLICY_ASK,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_ENUM (object_class, PROP_METADATA_ROTATION_POLICY,
|
||||
"metadata-rotation-policy",
|
||||
"Metadata rotation policy",
|
||||
METADATA_ROTATION_POLICY_BLURB,
|
||||
GIMP_TYPE_METADATA_ROTATION_POLICY,
|
||||
GIMP_METADATA_ROTATION_POLICY_ASK,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_PATH (object_class, PROP_COLOR_PROFILE_PATH,
|
||||
"color-profile-path",
|
||||
"Default color profile folder path",
|
||||
|
@ -604,6 +613,9 @@ gimp_dialog_config_set_property (GObject *object,
|
|||
case PROP_COLOR_PROFILE_POLICY:
|
||||
config->color_profile_policy = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_METADATA_ROTATION_POLICY:
|
||||
config->metadata_rotation_policy = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_PROFILE_PATH:
|
||||
if (config->color_profile_path)
|
||||
|
@ -804,6 +816,9 @@ gimp_dialog_config_get_property (GObject *object,
|
|||
case PROP_COLOR_PROFILE_POLICY:
|
||||
g_value_set_enum (value, config->color_profile_policy);
|
||||
break;
|
||||
case PROP_METADATA_ROTATION_POLICY:
|
||||
g_value_set_enum (value, config->metadata_rotation_policy);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_PROFILE_PATH:
|
||||
g_value_set_string (value, config->color_profile_path);
|
||||
|
|
|
@ -44,7 +44,8 @@ struct _GimpDialogConfig
|
|||
{
|
||||
GimpGuiConfig parent_instance;
|
||||
|
||||
GimpColorProfilePolicy color_profile_policy;
|
||||
GimpColorProfilePolicy color_profile_policy;
|
||||
GimpMetadataRotationPolicy metadata_rotation_policy;
|
||||
|
||||
gchar *color_profile_path;
|
||||
|
||||
|
|
|
@ -281,6 +281,9 @@ _("Speed of marching ants in the selection outline. This value is in " \
|
|||
_("GIMP will warn the user if an attempt is made to create an image that " \
|
||||
"would take more memory than the size specified here.")
|
||||
|
||||
#define METADATA_ROTATION_POLICY_BLURB \
|
||||
_("How to handle \"Orientation\" metadata when opening a file.")
|
||||
|
||||
#define MODULE_PATH_BLURB \
|
||||
"Sets the module search path."
|
||||
|
||||
|
|
|
@ -919,6 +919,37 @@ gimp_message_severity_get_type (void)
|
|||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
gimp_metadata_rotation_policy_get_type (void)
|
||||
{
|
||||
static const GEnumValue values[] =
|
||||
{
|
||||
{ GIMP_METADATA_ROTATION_POLICY_ASK, "GIMP_METADATA_ROTATION_POLICY_ASK", "ask" },
|
||||
{ GIMP_METADATA_ROTATION_POLICY_KEEP, "GIMP_METADATA_ROTATION_POLICY_KEEP", "keep" },
|
||||
{ GIMP_METADATA_ROTATION_POLICY_ROTATE, "GIMP_METADATA_ROTATION_POLICY_ROTATE", "rotate" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const GimpEnumDesc descs[] =
|
||||
{
|
||||
{ GIMP_METADATA_ROTATION_POLICY_ASK, NC_("metadata-rotation-policy", "Ask what to do"), NULL },
|
||||
{ GIMP_METADATA_ROTATION_POLICY_KEEP, NC_("metadata-rotation-policy", "Discard metadata without rotating"), NULL },
|
||||
{ GIMP_METADATA_ROTATION_POLICY_ROTATE, NC_("metadata-rotation-policy", "Rotate the image then discard metadata"), NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (! type))
|
||||
{
|
||||
type = g_enum_register_static ("GimpMetadataRotationPolicy", values);
|
||||
gimp_type_set_translation_context (type, "metadata-rotation-policy");
|
||||
gimp_enum_set_value_descriptions (type, descs);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
gimp_paste_type_get_type (void)
|
||||
{
|
||||
|
|
|
@ -419,6 +419,18 @@ typedef enum /*< pdb-skip >*/
|
|||
} GimpMessageSeverity;
|
||||
|
||||
|
||||
#define GIMP_TYPE_METADATA_ROTATION_POLICY (gimp_metadata_rotation_policy_get_type ())
|
||||
|
||||
GType gimp_metadata_rotation_policy_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef enum /*< pdb-skip >*/
|
||||
{
|
||||
GIMP_METADATA_ROTATION_POLICY_ASK, /*< desc="Ask what to do" >*/
|
||||
GIMP_METADATA_ROTATION_POLICY_KEEP, /*< desc="Discard metadata without rotating" >*/
|
||||
GIMP_METADATA_ROTATION_POLICY_ROTATE /*< desc="Rotate the image then discard metadata" >*/
|
||||
} GimpMetadataRotationPolicy;
|
||||
|
||||
|
||||
#define GIMP_TYPE_PASTE_TYPE (gimp_paste_type_get_type ())
|
||||
|
||||
GType gimp_paste_type_get_type (void) G_GNUC_CONST;
|
||||
|
|
|
@ -65,6 +65,7 @@ gimp_gui_init (Gimp *gimp)
|
|||
gimp->gui.recent_list_load = NULL;
|
||||
gimp->gui.get_mount_operation = NULL;
|
||||
gimp->gui.query_profile_policy = NULL;
|
||||
gimp->gui.query_rotation_policy = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -536,3 +537,19 @@ gimp_query_profile_policy (Gimp *gimp,
|
|||
|
||||
return GIMP_COLOR_PROFILE_POLICY_KEEP;
|
||||
}
|
||||
|
||||
GimpMetadataRotationPolicy
|
||||
gimp_query_rotation_policy (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpContext *context,
|
||||
gboolean *dont_ask)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), GIMP_METADATA_ROTATION_POLICY_ROTATE);
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_METADATA_ROTATION_POLICY_ROTATE);
|
||||
g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_METADATA_ROTATION_POLICY_ROTATE);
|
||||
|
||||
if (gimp->gui.query_rotation_policy)
|
||||
return gimp->gui.query_rotation_policy (gimp, image, context, dont_ask);
|
||||
|
||||
return GIMP_METADATA_ROTATION_POLICY_ROTATE;
|
||||
}
|
||||
|
|
|
@ -103,6 +103,12 @@ struct _GimpGui
|
|||
GimpColorRenderingIntent *intent,
|
||||
gboolean *bpc,
|
||||
gboolean *dont_ask);
|
||||
|
||||
GimpMetadataRotationPolicy
|
||||
(* query_rotation_policy) (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpContext *context,
|
||||
gboolean *dont_ask);
|
||||
};
|
||||
|
||||
|
||||
|
@ -196,5 +202,11 @@ GimpColorProfilePolicy
|
|||
gboolean *bpc,
|
||||
gboolean *dont_ask);
|
||||
|
||||
GimpMetadataRotationPolicy
|
||||
gimp_query_rotation_policy (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpContext *context,
|
||||
gboolean *dont_ask);
|
||||
|
||||
|
||||
#endif /* __GIMP_GUI_H__ */
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
#include <gexiv2/gexiv2.h>
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "config/gimpdialogconfig.h"
|
||||
|
||||
#include "vectors/gimpvectors.h"
|
||||
|
||||
#include "gimp.h"
|
||||
|
@ -29,6 +32,8 @@
|
|||
#include "gimpcontext.h"
|
||||
#include "gimpguide.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpimage-flip.h"
|
||||
#include "gimpimage-metadata.h"
|
||||
#include "gimpimage-rotate.h"
|
||||
#include "gimpimage-guides.h"
|
||||
#include "gimpimage-sample-points.h"
|
||||
|
@ -41,16 +46,23 @@
|
|||
#include "gimpsamplepoint.h"
|
||||
|
||||
|
||||
static void gimp_image_rotate_item_offset (GimpImage *image,
|
||||
GimpRotationType rotate_type,
|
||||
GimpItem *item,
|
||||
gint off_x,
|
||||
gint off_y);
|
||||
static void gimp_image_rotate_guides (GimpImage *image,
|
||||
GimpRotationType rotate_type);
|
||||
static void gimp_image_rotate_sample_points (GimpImage *image,
|
||||
GimpRotationType rotate_type);
|
||||
static void gimp_image_rotate_item_offset (GimpImage *image,
|
||||
GimpRotationType rotate_type,
|
||||
GimpItem *item,
|
||||
gint off_x,
|
||||
gint off_y);
|
||||
static void gimp_image_rotate_guides (GimpImage *image,
|
||||
GimpRotationType rotate_type);
|
||||
static void gimp_image_rotate_sample_points (GimpImage *image,
|
||||
GimpRotationType rotate_type);
|
||||
|
||||
static void gimp_image_metadata_rotate (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GExiv2Orientation orientation,
|
||||
GimpProgress *progress);
|
||||
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
void
|
||||
gimp_image_rotate (GimpImage *image,
|
||||
|
@ -214,6 +226,59 @@ gimp_image_rotate (GimpImage *image,
|
|||
gimp_unset_busy (image->gimp);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_import_rotation_metadata (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
gboolean interactive)
|
||||
{
|
||||
GimpMetadata *metadata;
|
||||
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
||||
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
|
||||
|
||||
metadata = gimp_image_get_metadata (image);
|
||||
|
||||
if (metadata)
|
||||
{
|
||||
GimpMetadataRotationPolicy policy;
|
||||
|
||||
policy = GIMP_DIALOG_CONFIG (image->gimp->config)->metadata_rotation_policy;
|
||||
if (policy == GIMP_METADATA_ROTATION_POLICY_ASK)
|
||||
{
|
||||
if (interactive)
|
||||
{
|
||||
gboolean dont_ask = FALSE;
|
||||
|
||||
policy = gimp_query_rotation_policy (image->gimp, image,
|
||||
context, &dont_ask);
|
||||
|
||||
if (dont_ask)
|
||||
{
|
||||
g_object_set (G_OBJECT (image->gimp->config),
|
||||
"metadata-rotation-policy", policy,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
policy = GIMP_METADATA_ROTATION_POLICY_ROTATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (policy == GIMP_METADATA_ROTATION_POLICY_ROTATE)
|
||||
gimp_image_metadata_rotate (image, context,
|
||||
gexiv2_metadata_get_orientation (GEXIV2_METADATA (metadata)),
|
||||
progress);
|
||||
|
||||
gexiv2_metadata_set_orientation (GEXIV2_METADATA (metadata),
|
||||
GEXIV2_ORIENTATION_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Private Functions */
|
||||
|
||||
static void
|
||||
gimp_image_rotate_item_offset (GimpImage *image,
|
||||
|
@ -375,3 +440,50 @@ gimp_image_rotate_sample_points (GimpImage *image,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_image_metadata_rotate (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GExiv2Orientation orientation,
|
||||
GimpProgress *progress)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case GEXIV2_ORIENTATION_UNSPECIFIED:
|
||||
case GEXIV2_ORIENTATION_NORMAL: /* standard orientation, do nothing */
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_HFLIP:
|
||||
gimp_image_flip (image, context, GIMP_ORIENTATION_HORIZONTAL, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_180:
|
||||
gimp_image_rotate (image, context, GIMP_ROTATE_180, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_VFLIP:
|
||||
gimp_image_flip (image, context, GIMP_ORIENTATION_VERTICAL, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_HFLIP: /* flipped diagonally around '\' */
|
||||
gimp_image_rotate (image, context, GIMP_ROTATE_90, progress);
|
||||
gimp_image_flip (image, context, GIMP_ORIENTATION_HORIZONTAL, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90: /* 90 CW */
|
||||
gimp_image_rotate (image, context, GIMP_ROTATE_90, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_VFLIP: /* flipped diagonally around '/' */
|
||||
gimp_image_rotate (image, context, GIMP_ROTATE_90, progress);
|
||||
gimp_image_flip (image, context, GIMP_ORIENTATION_VERTICAL, progress);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_270: /* 90 CCW */
|
||||
gimp_image_rotate (image, context, GIMP_ROTATE_270, progress);
|
||||
break;
|
||||
|
||||
default: /* shouldn't happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,14 @@
|
|||
#define __GIMP_IMAGE_ROTATE_H__
|
||||
|
||||
|
||||
void gimp_image_rotate (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpRotationType rotate_type,
|
||||
GimpProgress *progress);
|
||||
void gimp_image_rotate (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpRotationType rotate_type,
|
||||
GimpProgress *progress);
|
||||
|
||||
void gimp_image_import_rotation_metadata (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
gboolean interactive);
|
||||
|
||||
#endif /* __GIMP_IMAGE_ROTATE_H__ */
|
||||
|
|
|
@ -67,6 +67,7 @@ libappdialogs_a_sources = \
|
|||
layer-options-dialog.h \
|
||||
lebl-dialog.c \
|
||||
lebl-dialog.h \
|
||||
metadata-rotation-import-dialog.c \
|
||||
module-dialog.c \
|
||||
module-dialog.h \
|
||||
palette-import-dialog.c \
|
||||
|
|
|
@ -25,6 +25,7 @@ libappdialogs_sources = [
|
|||
'layer-add-mask-dialog.c',
|
||||
'layer-options-dialog.c',
|
||||
'lebl-dialog.c',
|
||||
'metadata-rotation-import-dialog.c',
|
||||
'module-dialog.c',
|
||||
'palette-import-dialog.c',
|
||||
'preferences-dialog-utils.c',
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* metadata-rotation-import-dialog.h
|
||||
* Copyright (C) 2020 Jehan
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gexiv2/gexiv2.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
#include "libgimpwidgets/gimpwidgets.h"
|
||||
|
||||
#include "dialogs-types.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpcontext.h"
|
||||
#include "core/gimpimage.h"
|
||||
#include "core/gimpimage-metadata.h"
|
||||
#include "core/gimppickable.h"
|
||||
|
||||
#include "widgets/gimphelp-ids.h"
|
||||
#include "widgets/gimpviewabledialog.h"
|
||||
#include "widgets/gimpwidgets-constructors.h"
|
||||
|
||||
#include "metadata-rotation-import-dialog.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
static GimpMetadataRotationPolicy gimp_image_metadata_rotate_dialog (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GExiv2Orientation orientation,
|
||||
gboolean *dont_ask);
|
||||
static GdkPixbuf * gimp_image_metadata_rotate_pixbuf (GdkPixbuf *pixbuf,
|
||||
GExiv2Orientation orientation);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
GimpMetadataRotationPolicy
|
||||
metadata_rotation_import_dialog_run (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GtkWidget *parent,
|
||||
gboolean *dont_ask)
|
||||
{
|
||||
GimpMetadata *metadata;
|
||||
GExiv2Orientation orientation;
|
||||
|
||||
metadata = gimp_image_get_metadata (image);
|
||||
orientation = gexiv2_metadata_get_orientation (GEXIV2_METADATA (metadata));
|
||||
|
||||
if (orientation <= GEXIV2_ORIENTATION_NORMAL ||
|
||||
orientation > GEXIV2_ORIENTATION_MAX)
|
||||
return GIMP_METADATA_ROTATION_POLICY_KEEP;
|
||||
|
||||
return gimp_image_metadata_rotate_dialog (image, context, orientation, dont_ask);
|
||||
}
|
||||
|
||||
static GimpMetadataRotationPolicy
|
||||
gimp_image_metadata_rotate_dialog (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GExiv2Orientation orientation,
|
||||
gboolean *dont_ask)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *toggle;
|
||||
const gchar *name;
|
||||
gchar *title;
|
||||
GdkPixbuf *pixbuf;
|
||||
gint width;
|
||||
gint scale_factor;
|
||||
gint height;
|
||||
gint response;
|
||||
|
||||
name = gimp_image_get_display_name (image);
|
||||
title = g_strdup_printf (_("Rotate %s?"), name);
|
||||
|
||||
dialog = gimp_dialog_new (title, "gimp-metadata-rotate-dialog",
|
||||
NULL, 0, NULL, NULL,
|
||||
|
||||
_("_Keep Original"), GTK_RESPONSE_CANCEL,
|
||||
_("_Rotate"), GTK_RESPONSE_OK,
|
||||
|
||||
NULL);
|
||||
|
||||
g_free (title);
|
||||
|
||||
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
||||
GTK_RESPONSE_OK,
|
||||
GTK_RESPONSE_CANCEL,
|
||||
-1);
|
||||
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
|
||||
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
main_vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (main_vbox);
|
||||
|
||||
scale_factor = gtk_widget_get_scale_factor (main_vbox);
|
||||
width = gimp_image_get_width (image);
|
||||
height = gimp_image_get_height (image);
|
||||
|
||||
#define MAX_THUMBNAIL_SIZE (128 * scale_factor)
|
||||
if (width > MAX_THUMBNAIL_SIZE || height > MAX_THUMBNAIL_SIZE)
|
||||
{
|
||||
/* Adjust the width/height ratio to a maximum size (relative to
|
||||
* current display scale factor.
|
||||
*/
|
||||
if (width > height)
|
||||
{
|
||||
height = MAX_THUMBNAIL_SIZE * height / width;
|
||||
width = MAX_THUMBNAIL_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = MAX_THUMBNAIL_SIZE * width / height;
|
||||
height = MAX_THUMBNAIL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pickable_flush (GIMP_PICKABLE (image));
|
||||
pixbuf = gimp_viewable_get_pixbuf (GIMP_VIEWABLE (image), context,
|
||||
width, height);
|
||||
if (pixbuf)
|
||||
{
|
||||
GdkPixbuf *rotated;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
label = gtk_label_new (_("Original"));
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
image = gtk_image_new_from_pixbuf (pixbuf);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), image, FALSE, FALSE, 0);
|
||||
gtk_widget_show (image);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
label = gtk_label_new (_("Rotated"));
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
rotated = gimp_image_metadata_rotate_pixbuf (pixbuf, orientation);
|
||||
|
||||
image = gtk_image_new_from_pixbuf (rotated);
|
||||
g_object_unref (rotated);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), image, FALSE, FALSE, 0);
|
||||
gtk_widget_show (image);
|
||||
}
|
||||
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"label", _("This image contains Exif orientation "
|
||||
"metadata."),
|
||||
"wrap", TRUE,
|
||||
"justify", GTK_JUSTIFY_LEFT,
|
||||
"xalign", 0.0,
|
||||
"yalign", 0.5,
|
||||
NULL);
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_SCALE, PANGO_SCALE_LARGE,
|
||||
PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
|
||||
-1);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"label", _("Would you like to rotate the image?"),
|
||||
"wrap", TRUE,
|
||||
"justify", GTK_JUSTIFY_LEFT,
|
||||
"xalign", 0.0,
|
||||
"yalign", 0.5,
|
||||
NULL);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
toggle = gtk_check_button_new_with_mnemonic (_("_Don't ask me again"));
|
||||
gtk_box_pack_end (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
|
||||
gtk_widget_show (toggle);
|
||||
|
||||
response = gimp_dialog_run (GIMP_DIALOG (dialog));
|
||||
*dont_ask = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)));
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
return (response == GTK_RESPONSE_OK) ? GIMP_METADATA_ROTATION_POLICY_ROTATE : GIMP_COLOR_PROFILE_POLICY_KEEP;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
gimp_image_metadata_rotate_pixbuf (GdkPixbuf *pixbuf,
|
||||
GExiv2Orientation orientation)
|
||||
{
|
||||
GdkPixbuf *rotated = NULL;
|
||||
GdkPixbuf *temp;
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case GEXIV2_ORIENTATION_UNSPECIFIED:
|
||||
case GEXIV2_ORIENTATION_NORMAL: /* standard orientation, do nothing */
|
||||
rotated = g_object_ref (pixbuf);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_HFLIP:
|
||||
rotated = gdk_pixbuf_flip (pixbuf, TRUE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_180:
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_VFLIP:
|
||||
rotated = gdk_pixbuf_flip (pixbuf, FALSE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_HFLIP: /* flipped diagonally around '\' */
|
||||
temp = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
rotated = gdk_pixbuf_flip (temp, TRUE);
|
||||
g_object_unref (temp);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90: /* 90 CW */
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_VFLIP: /* flipped diagonally around '/' */
|
||||
temp = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
rotated = gdk_pixbuf_flip (temp, FALSE);
|
||||
g_object_unref (temp);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_270: /* 90 CCW */
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
|
||||
break;
|
||||
|
||||
default: /* shouldn't happen */
|
||||
break;
|
||||
}
|
||||
|
||||
return rotated;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* metadata-rotation-import-dialog.h
|
||||
* Copyright (C) 2020 Jehan
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __METADATA_ROTATION_IMPORT_DIALOG_H__
|
||||
#define __METADATA_ROTATION_IMPORT_DIALOG_H__
|
||||
|
||||
|
||||
GimpMetadataRotationPolicy metadata_rotation_import_dialog_run (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GtkWidget *parent,
|
||||
gboolean *dont_ask);
|
||||
|
||||
|
||||
#endif /* __METADATA_ROTATION_IMPORT_DIALOG_H__*/
|
|
@ -1518,6 +1518,9 @@ prefs_dialog_new (Gimp *gimp,
|
|||
button = prefs_enum_combo_box_add (object, "color-profile-policy", 0, 0,
|
||||
_("Color _profile policy:"),
|
||||
GTK_GRID (grid), 0, size_group);
|
||||
button = prefs_enum_combo_box_add (object, "metadata-rotation-policy", 0, 0,
|
||||
_("Metadata _rotation policy:"),
|
||||
GTK_GRID (grid), 1, size_group);
|
||||
|
||||
/* Export Policies */
|
||||
vbox2 = prefs_frame_new (_("Export Policies"),
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "core/gimpimage.h"
|
||||
#include "core/gimpimage-color-profile.h"
|
||||
#include "core/gimpimage-convert-precision.h"
|
||||
#include "core/gimpimage-rotate.h"
|
||||
#include "core/gimplayer.h"
|
||||
#include "core/gimpprogress.h"
|
||||
|
||||
|
@ -100,6 +101,7 @@ file_import_image (GimpImage *image,
|
|||
}
|
||||
|
||||
gimp_image_import_color_profile (image, context, progress, interactive);
|
||||
gimp_image_import_rotation_metadata (image, context, progress, interactive);
|
||||
|
||||
/* Remember the import source */
|
||||
gimp_image_set_imported_file (image, file);
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
#include "menus/menus.h"
|
||||
|
||||
#include "dialogs/color-profile-import-dialog.h"
|
||||
#include "dialogs/metadata-rotation-import-dialog.h"
|
||||
|
||||
#include "gui.h"
|
||||
#include "gui-message.h"
|
||||
|
@ -179,6 +180,11 @@ static GimpColorProfilePolicy
|
|||
GimpColorRenderingIntent *intent,
|
||||
gboolean *bpc,
|
||||
gboolean *dont_ask);
|
||||
static GimpMetadataRotationPolicy
|
||||
gui_query_rotation_policy (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpContext *context,
|
||||
gboolean *dont_ask);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
@ -214,6 +220,7 @@ gui_vtable_init (Gimp *gimp)
|
|||
gimp->gui.recent_list_load = gui_recent_list_load;
|
||||
gimp->gui.get_mount_operation = gui_get_mount_operation;
|
||||
gimp->gui.query_profile_policy = gui_query_profile_policy;
|
||||
gimp->gui.query_rotation_policy = gui_query_rotation_policy;
|
||||
}
|
||||
|
||||
|
||||
|
@ -906,3 +913,13 @@ gui_query_profile_policy (Gimp *gimp,
|
|||
intent, bpc,
|
||||
dont_ask);
|
||||
}
|
||||
|
||||
static GimpMetadataRotationPolicy
|
||||
gui_query_rotation_policy (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpContext *context,
|
||||
gboolean *dont_ask)
|
||||
{
|
||||
return metadata_rotation_import_dialog_run (image, context,
|
||||
NULL, dont_ask);
|
||||
}
|
||||
|
|
|
@ -183,7 +183,6 @@ libgimpui_introspectable_headers = \
|
|||
../libgimp/gimpfontselectbutton.h \
|
||||
../libgimp/gimpgradientselectbutton.h \
|
||||
../libgimp/gimpimagecombobox.h \
|
||||
../libgimp/gimpimagemetadata-interactive.h \
|
||||
../libgimp/gimpitemcombobox.h \
|
||||
../libgimp/gimppaletteselectbutton.h \
|
||||
../libgimp/gimppatternselectbutton.h \
|
||||
|
@ -204,7 +203,6 @@ libgimpui_introspectable = \
|
|||
../libgimp/gimpfontselectbutton.c \
|
||||
../libgimp/gimpgradientselectbutton.c \
|
||||
../libgimp/gimpimagecombobox.c \
|
||||
../libgimp/gimpimagemetadata-interactive.c \
|
||||
../libgimp/gimpitemcombobox.c \
|
||||
../libgimp/gimppaletteselectbutton.c \
|
||||
../libgimp/gimppatternselectbutton.c \
|
||||
|
|
|
@ -1,369 +0,0 @@
|
|||
/* LIBGIMP - The GIMP Library
|
||||
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* gimpimagemetadata-interactive.c
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gexiv2/gexiv2.h>
|
||||
|
||||
#include "gimp.h"
|
||||
#include "gimpui.h"
|
||||
#include "gimpimagemetadata.h"
|
||||
|
||||
#include "libgimp-intl.h"
|
||||
|
||||
|
||||
static gboolean gimp_image_metadata_rotate_query (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata);
|
||||
static gboolean gimp_image_metadata_rotate_dialog (GimpImage *image,
|
||||
GExiv2Orientation orientation,
|
||||
const gchar *parasite_name);
|
||||
static GdkPixbuf * gimp_image_metadata_rotate_pixbuf (GdkPixbuf *pixbuf,
|
||||
GExiv2Orientation orientation);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
/**
|
||||
* gimp_image_metadata_load_finish:
|
||||
* @image: The image
|
||||
* @mime_type: The loaded file's mime-type
|
||||
* @metadata: The metadata to set on the image
|
||||
* @flags: Flags to specify what of the metadata to apply to the image
|
||||
* @interactive: Whether this function is allowed to query info with dialogs
|
||||
*
|
||||
* Applies the @metadata previously loaded with
|
||||
* gimp_image_metadata_load_prepare() to the image, taking into account
|
||||
* the passed @flags.
|
||||
*
|
||||
* This function is the interactive alternative to
|
||||
* gimp_image_metadata_load_finish_batch() which is allowed to query
|
||||
* info with dialogs. For instance, if GIMP_METADATA_LOAD_ORIENTATION
|
||||
* flag is set, it will popup a dialog asking whether one wants to
|
||||
* rotate the image according to the orientation set in the metadata
|
||||
* (displaying small previews of both versions).
|
||||
* If @interactive is %FALSE, this behaves exactly the same as
|
||||
* gimp_image_metadata_load_finish_batch().
|
||||
*
|
||||
* Since: 2.10
|
||||
*/
|
||||
void
|
||||
gimp_image_metadata_load_finish (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags,
|
||||
gboolean interactive)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (GEXIV2_IS_METADATA (metadata));
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
if (flags & GIMP_METADATA_LOAD_ORIENTATION)
|
||||
{
|
||||
if (! gimp_image_metadata_rotate_query (image, mime_type,
|
||||
metadata))
|
||||
{
|
||||
/* If one explicitly asks not to rotate the image, just
|
||||
* drop the "Orientation" metadata because that's how one
|
||||
* wants to see the image.
|
||||
*
|
||||
* Note that there might be special cases where one wants
|
||||
* to keep the pixel as-is while keeping rotation through
|
||||
* metadata. But we don't have good enough metadata
|
||||
* support for this yet, in particular we don't honor the
|
||||
* orientation metadata when viewing the image. So this
|
||||
* only ends up in unexpected exports with rotation
|
||||
* because people forgot there was such metadata set and
|
||||
* stored by GIMP. If maybe some day we have code to honor
|
||||
* orientation while viewing an image, then we can do this
|
||||
* a bit cleverer.
|
||||
*/
|
||||
gexiv2_metadata_set_orientation (GEXIV2_METADATA (metadata),
|
||||
GEXIV2_ORIENTATION_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gimp_image_metadata_load_finish_batch (image, mime_type, metadata, flags);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static gboolean
|
||||
gimp_image_metadata_rotate_query (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata)
|
||||
{
|
||||
GimpParasite *parasite;
|
||||
gchar *parasite_name;
|
||||
GExiv2Orientation orientation;
|
||||
gboolean query = TRUE;
|
||||
|
||||
orientation = gexiv2_metadata_get_orientation (GEXIV2_METADATA (metadata));
|
||||
|
||||
if (orientation <= GEXIV2_ORIENTATION_NORMAL ||
|
||||
orientation > GEXIV2_ORIENTATION_MAX)
|
||||
return FALSE;
|
||||
|
||||
parasite_name = g_strdup_printf ("gimp-metadata-exif-rotate(%s)", mime_type);
|
||||
|
||||
parasite = gimp_get_parasite (parasite_name);
|
||||
|
||||
if (parasite)
|
||||
{
|
||||
if (strncmp (gimp_parasite_data (parasite), "yes",
|
||||
gimp_parasite_data_size (parasite)) == 0)
|
||||
{
|
||||
query = FALSE;
|
||||
}
|
||||
else if (strncmp (gimp_parasite_data (parasite), "no",
|
||||
gimp_parasite_data_size (parasite)) == 0)
|
||||
{
|
||||
gimp_parasite_free (parasite);
|
||||
g_free (parasite_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gimp_parasite_free (parasite);
|
||||
}
|
||||
|
||||
if (query && ! gimp_image_metadata_rotate_dialog (image,
|
||||
orientation,
|
||||
parasite_name))
|
||||
{
|
||||
g_free (parasite_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (parasite_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_image_metadata_rotate_dialog (GimpImage *image,
|
||||
GExiv2Orientation orientation,
|
||||
const gchar *parasite_name)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *toggle;
|
||||
GdkPixbuf *pixbuf;
|
||||
gchar *name;
|
||||
gchar *title;
|
||||
gint response;
|
||||
|
||||
name = gimp_image_get_name (image);
|
||||
title = g_strdup_printf (_("Rotate %s?"), name);
|
||||
g_free (name);
|
||||
|
||||
dialog = gimp_dialog_new (title, "gimp-metadata-rotate-dialog",
|
||||
NULL, 0, NULL, NULL,
|
||||
|
||||
_("_Keep Original"), GTK_RESPONSE_CANCEL,
|
||||
_("_Rotate"), GTK_RESPONSE_OK,
|
||||
|
||||
NULL);
|
||||
|
||||
g_free (title);
|
||||
|
||||
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
||||
GTK_RESPONSE_OK,
|
||||
GTK_RESPONSE_CANCEL,
|
||||
-1);
|
||||
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
gimp_window_set_transient (GTK_WINDOW (dialog));
|
||||
|
||||
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
main_vbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (main_vbox);
|
||||
|
||||
#define THUMBNAIL_SIZE 128
|
||||
|
||||
pixbuf = gimp_image_get_thumbnail (image,
|
||||
THUMBNAIL_SIZE, THUMBNAIL_SIZE,
|
||||
GIMP_PIXBUF_SMALL_CHECKS);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
GdkPixbuf *rotated;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
label = gtk_label_new (_("Original"));
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
image = gtk_image_new_from_pixbuf (pixbuf);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), image, FALSE, FALSE, 0);
|
||||
gtk_widget_show (image);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
label = gtk_label_new (_("Rotated"));
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
rotated = gimp_image_metadata_rotate_pixbuf (pixbuf, orientation);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
image = gtk_image_new_from_pixbuf (rotated);
|
||||
g_object_unref (rotated);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), image, FALSE, FALSE, 0);
|
||||
gtk_widget_show (image);
|
||||
}
|
||||
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"label", _("This image contains Exif orientation "
|
||||
"metadata."),
|
||||
"wrap", TRUE,
|
||||
"justify", GTK_JUSTIFY_LEFT,
|
||||
"xalign", 0.0,
|
||||
"yalign", 0.5,
|
||||
NULL);
|
||||
gimp_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_SCALE, PANGO_SCALE_LARGE,
|
||||
PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
|
||||
-1);
|
||||
/* eek */
|
||||
gtk_widget_set_size_request (GTK_WIDGET (label),
|
||||
2 * THUMBNAIL_SIZE + 12, -1);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"label", _("Would you like to rotate the image?"),
|
||||
"wrap", TRUE,
|
||||
"justify", GTK_JUSTIFY_LEFT,
|
||||
"xalign", 0.0,
|
||||
"yalign", 0.5,
|
||||
NULL);
|
||||
/* eek */
|
||||
gtk_widget_set_size_request (GTK_WIDGET (label),
|
||||
2 * THUMBNAIL_SIZE + 12, -1);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
toggle = gtk_check_button_new_with_mnemonic (_("_Don't ask me again"));
|
||||
gtk_box_pack_end (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
|
||||
gtk_widget_show (toggle);
|
||||
|
||||
response = gimp_dialog_run (GIMP_DIALOG (dialog));
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)))
|
||||
{
|
||||
GimpParasite *parasite;
|
||||
const gchar *str = (response == GTK_RESPONSE_OK) ? "yes" : "no";
|
||||
|
||||
parasite = gimp_parasite_new (parasite_name,
|
||||
GIMP_PARASITE_PERSISTENT,
|
||||
strlen (str), str);
|
||||
gimp_attach_parasite (parasite);
|
||||
gimp_parasite_free (parasite);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
return (response == GTK_RESPONSE_OK);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
gimp_image_metadata_rotate_pixbuf (GdkPixbuf *pixbuf,
|
||||
GExiv2Orientation orientation)
|
||||
{
|
||||
GdkPixbuf *rotated = NULL;
|
||||
GdkPixbuf *temp;
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case GEXIV2_ORIENTATION_UNSPECIFIED:
|
||||
case GEXIV2_ORIENTATION_NORMAL: /* standard orientation, do nothing */
|
||||
rotated = g_object_ref (pixbuf);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_HFLIP:
|
||||
rotated = gdk_pixbuf_flip (pixbuf, TRUE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_180:
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_VFLIP:
|
||||
rotated = gdk_pixbuf_flip (pixbuf, FALSE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_HFLIP: /* flipped diagonally around '\' */
|
||||
temp = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
rotated = gdk_pixbuf_flip (temp, TRUE);
|
||||
g_object_unref (temp);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90: /* 90 CW */
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_90_VFLIP: /* flipped diagonally around '/' */
|
||||
temp = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
||||
rotated = gdk_pixbuf_flip (temp, FALSE);
|
||||
g_object_unref (temp);
|
||||
break;
|
||||
|
||||
case GEXIV2_ORIENTATION_ROT_270: /* 90 CCW */
|
||||
rotated = gdk_pixbuf_rotate_simple (pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
|
||||
break;
|
||||
|
||||
default: /* shouldn't happen */
|
||||
break;
|
||||
}
|
||||
|
||||
return rotated;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/* LIBGIMP - The GIMP Library
|
||||
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* gimpimagemetadata-interactive.h
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
|
||||
#error "Only <libgimp/gimpui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __GIMP_IMAGE_METADATA_INTERACTIVE_H__
|
||||
#define __GIMP_IMAGE_METADATA_INTERACTIVE_H__
|
||||
|
||||
|
||||
void gimp_image_metadata_load_finish (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags,
|
||||
gboolean interactive);
|
||||
|
||||
|
||||
#endif /* __GIMP_IMAGE_METADATA_INTERACTIVE_H__ */
|
|
@ -51,8 +51,7 @@ static void gimp_image_metadata_rotate (GimpImage *image,
|
|||
* @error: Return location for error
|
||||
*
|
||||
* Loads and returns metadata from @file to be passed into
|
||||
* gimp_image_metadata_load_finish() or
|
||||
* gimp_image_metadata_load_finish_batch().
|
||||
* gimp_image_metadata_load_finish().
|
||||
*
|
||||
* Returns: (transfer full): The file's metadata.
|
||||
*
|
||||
|
@ -82,7 +81,7 @@ gimp_image_metadata_load_prepare (GimpImage *image,
|
|||
}
|
||||
|
||||
/**
|
||||
* gimp_image_metadata_load_finish_batch:
|
||||
* gimp_image_metadata_load_finish:
|
||||
* @image: The image
|
||||
* @mime_type: The loaded file's mime-type
|
||||
* @metadata: The metadata to set on the image
|
||||
|
@ -92,24 +91,13 @@ gimp_image_metadata_load_prepare (GimpImage *image,
|
|||
* gimp_image_metadata_load_prepare() to the image, taking into account
|
||||
* the passed @flags.
|
||||
*
|
||||
* Some metadata may involve some image changes and are better asked for
|
||||
* confirmation. For instance the orientation metadata may be wrong at
|
||||
* times (because it depends usually on camera sensors and the rotated
|
||||
* image may not be what one expects). If the related flag is set (i.e.
|
||||
* GIMP_METADATA_LOAD_ORIENTATION for orientation), then the change will
|
||||
* be automatically executed (i.e. the image will be rotated) without
|
||||
* any human interaction.
|
||||
*
|
||||
* If you wish such edit to be queried interactively with dialogs, use
|
||||
* gimp_image_metadata_load_finish() instead, from libgimpui.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
void
|
||||
gimp_image_metadata_load_finish_batch (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags)
|
||||
gimp_image_metadata_load_finish (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
|
@ -153,13 +141,10 @@ gimp_image_metadata_load_finish_batch (GimpImage *image,
|
|||
}
|
||||
}
|
||||
|
||||
if (flags & GIMP_METADATA_LOAD_ORIENTATION)
|
||||
if (! (flags & GIMP_METADATA_LOAD_ORIENTATION))
|
||||
{
|
||||
gimp_image_metadata_rotate (image,
|
||||
gexiv2_metadata_get_orientation (GEXIV2_METADATA (metadata)));
|
||||
|
||||
gexiv2_metadata_set_orientation (GEXIV2_METADATA (metadata),
|
||||
GEXIV2_ORIENTATION_NORMAL);
|
||||
GEXIV2_ORIENTATION_UNSPECIFIED);
|
||||
}
|
||||
|
||||
if (flags & GIMP_METADATA_LOAD_COLORSPACE)
|
||||
|
|
|
@ -35,10 +35,10 @@ GimpMetadata * gimp_image_metadata_load_prepare (GimpImage *image,
|
|||
const gchar *mime_type,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
void gimp_image_metadata_load_finish_batch (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags);
|
||||
void gimp_image_metadata_load_finish (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags flags);
|
||||
|
||||
GimpMetadata * gimp_image_metadata_save_prepare (GimpImage *image,
|
||||
const gchar *mime_type,
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <libgimp/gimpfontselectbutton.h>
|
||||
#include <libgimp/gimpgradientselectbutton.h>
|
||||
#include <libgimp/gimpimagecombobox.h>
|
||||
#include <libgimp/gimpimagemetadata-interactive.h>
|
||||
#include <libgimp/gimpitemcombobox.h>
|
||||
#include <libgimp/gimppaletteselectbutton.h>
|
||||
#include <libgimp/gimppatternselectbutton.h>
|
||||
|
|
|
@ -235,7 +235,6 @@ libgimpui_sources_introspectable = [
|
|||
'gimpfontselectbutton.c',
|
||||
'gimpgradientselectbutton.c',
|
||||
'gimpimagecombobox.c',
|
||||
'gimpimagemetadata-interactive.c',
|
||||
'gimpitemcombobox.c',
|
||||
'gimppaletteselectbutton.c',
|
||||
'gimppatternselectbutton.c',
|
||||
|
@ -266,7 +265,6 @@ libgimpui_headers_introspectable = [
|
|||
'gimpfontselectbutton.h',
|
||||
'gimpgradientselectbutton.h',
|
||||
'gimpimagecombobox.h',
|
||||
'gimpimagemetadata-interactive.h',
|
||||
'gimpitemcombobox.h',
|
||||
'gimppaletteselectbutton.h',
|
||||
'gimppatternselectbutton.h',
|
||||
|
|
|
@ -1252,8 +1252,7 @@ load_image (GFile *file,
|
|||
}
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/heif",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -333,8 +333,7 @@ jp2_load (GimpProcedure *procedure,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/jp2",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
|
|
@ -382,8 +382,7 @@ png_load (GimpProcedure *procedure,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/png",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ load_image (GFile *file,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/exr",
|
||||
metadata, flags, interactive);
|
||||
metadata, flags);
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
||||
|
|
|
@ -274,7 +274,6 @@ jpeg_load (GimpProcedure *procedure,
|
|||
{
|
||||
GimpValueArray *return_vals;
|
||||
GimpImage *image;
|
||||
gboolean interactive;
|
||||
gboolean resolution_loaded = FALSE;
|
||||
GError *error = NULL;
|
||||
|
||||
|
@ -289,11 +288,9 @@ jpeg_load (GimpProcedure *procedure,
|
|||
case GIMP_RUN_INTERACTIVE:
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
interactive = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
interactive = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -315,8 +312,7 @@ jpeg_load (GimpProcedure *procedure,
|
|||
flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/jpeg",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
|
|
@ -236,7 +236,6 @@ psd_load (GimpProcedure *procedure,
|
|||
GimpValueArray *return_vals;
|
||||
gboolean resolution_loaded = FALSE;
|
||||
gboolean profile_loaded = FALSE;
|
||||
gboolean interactive;
|
||||
GimpImage *image;
|
||||
GimpMetadata *metadata;
|
||||
GError *error = NULL;
|
||||
|
@ -249,10 +248,8 @@ psd_load (GimpProcedure *procedure,
|
|||
case GIMP_RUN_INTERACTIVE:
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
interactive = TRUE;
|
||||
break;
|
||||
default:
|
||||
interactive = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -281,8 +278,7 @@ psd_load (GimpProcedure *procedure,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/x-psd",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
|
|
@ -307,8 +307,7 @@ tiff_load (GimpProcedure *procedure,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/tiff",
|
||||
metadata, flags,
|
||||
run_mode == GIMP_RUN_INTERACTIVE);
|
||||
metadata, flags);
|
||||
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
|
|
@ -285,8 +285,7 @@ load_image (GFile *file,
|
|||
flags &= ~GIMP_METADATA_LOAD_COLORSPACE;
|
||||
|
||||
gimp_image_metadata_load_finish (image, "image/webp",
|
||||
metadata, flags,
|
||||
interactive);
|
||||
metadata, flags);
|
||||
g_object_unref (metadata);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ libgimp/gimpexport.c
|
|||
libgimp/gimpfontselectbutton.c
|
||||
libgimp/gimpgradientselectbutton.c
|
||||
libgimp/gimpimagemetadata.c
|
||||
libgimp/gimpimagemetadata-interactive.c
|
||||
libgimp/gimpimagemetadata-save.c
|
||||
libgimp/gimppaletteselectbutton.c
|
||||
libgimp/gimppatternselectbutton.c
|
||||
|
|
Loading…
Reference in New Issue