[gimp/GimpFileDialog-refactoring: 3/3] app: add a "Scale Image for Export" feature in the export dialog.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/GimpFileDialog-refactoring: 3/3] app: add a "Scale Image for Export" feature in the export dialog.
- Date: Wed, 2 Sep 2015 18:09:05 +0000 (UTC)
commit 9b20d97df3e24b9da0afc92efe8d4410dfe5fcea
Author: Jehan <jehan girinstud io>
Date: Wed Sep 2 13:54:49 2015 +0200
app: add a "Scale Image for Export" feature in the export dialog.
Based on the previous refactoring work, we can provide on-export
specific features. This first feature allows user to resize images
on export without touching the original image.
app/core/gimpimage-private.h | 8 ++
app/core/gimpimage.c | 50 +++++++++++++
app/core/gimpimage.h | 17 +++++
app/dialogs/file-save-dialog.c | 23 ++++++
app/file/file-save.c | 86 ++++++++++++++++++++++-
app/widgets/gimpexportdialog.c | 154 ++++++++++++++++++++++++++++++++++++++--
app/widgets/gimpexportdialog.h | 15 ++++-
app/widgets/gimpsizebox.c | 65 +++++++++++++++++-
app/widgets/gimpsizebox.h | 8 ++
9 files changed, 417 insertions(+), 9 deletions(-)
---
diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h
index bfc85d1..df9e099 100644
--- a/app/core/gimpimage-private.h
+++ b/app/core/gimpimage-private.h
@@ -65,6 +65,14 @@ struct _GimpImagePrivate
GFile *save_a_copy_file; /* the image's save-a-copy file */
GFile *untitled_file; /* a file saying "Untitled" */
+ gint export_width; /* width in pixels for export */
+ gint export_height; /* height in pixels for export */
+ GimpUnit export_unit; /* width/height display unit */
+ gdouble export_xresolution; /* x-res in ppi for export */
+ gdouble export_yresolution; /* y-res in ppi for export */
+ GimpUnit export_res_unit; /* resolution display unit */
+ GimpInterpolationType export_interpolation; /* interpolation for export */
+
gboolean xcf_compat_mode; /* if possible, save compat XCF */
gint dirty; /* dirty flag -- # of ops */
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 833a5d4..b466182 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -2365,6 +2365,56 @@ gimp_image_get_xcf_version (GimpImage *image,
}
void
+gimp_image_set_export_dimensions (GimpImage *image,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ GimpInterpolationType interpolation)
+{
+ GimpImagePrivate *private;
+
+ g_return_if_fail (GIMP_IS_IMAGE (image));
+
+ private = GIMP_IMAGE_GET_PRIVATE (image);
+
+ private->export_width = width;
+ private->export_height = height;
+ private->export_unit = unit;
+ private->export_xresolution = xresolution;
+ private->export_yresolution = yresolution;
+ private->export_res_unit = resolution_unit;
+ private->export_interpolation = interpolation;
+}
+
+void
+gimp_image_get_export_dimensions (GimpImage *image,
+ gint *width,
+ gint *height,
+ GimpUnit *unit,
+ gdouble *xresolution,
+ gdouble *yresolution,
+ GimpUnit *resolution_unit,
+ GimpInterpolationType *interpolation)
+{
+ GimpImagePrivate *private;
+
+ g_return_if_fail (GIMP_IS_IMAGE (image));
+
+ private = GIMP_IMAGE_GET_PRIVATE (image);
+
+ *width = private->export_width;
+ *height = private->export_height;
+ *unit = private->export_unit;
+ *xresolution = private->export_xresolution;
+ *yresolution = private->export_yresolution;
+ *resolution_unit = private->export_res_unit;
+ *interpolation = private->export_interpolation;
+}
+
+void
gimp_image_set_xcf_compat_mode (GimpImage *image,
gboolean compat_mode)
{
diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h
index 28d7554..234a28c 100644
--- a/app/core/gimpimage.h
+++ b/app/core/gimpimage.h
@@ -171,6 +171,23 @@ gint gimp_image_get_xcf_version (GimpImage *image,
gint *gimp_version,
const gchar **version_string);
+void gimp_image_set_export_dimensions (GimpImage *image,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ GimpInterpolationType interpolation);
+void gimp_image_get_export_dimensions (GimpImage *image,
+ gint *width,
+ gint *height,
+ GimpUnit *unit,
+ gdouble *xresolution,
+ gdouble *yresolution,
+ GimpUnit *resolution_unit,
+ GimpInterpolationType *interpolation);
+
void gimp_image_set_xcf_compat_mode (GimpImage *image,
gboolean compat_mode);
gboolean gimp_image_get_xcf_compat_mode (const GimpImage *image);
diff --git a/app/dialogs/file-save-dialog.c b/app/dialogs/file-save-dialog.c
index 42b47ec..6607147 100644
--- a/app/dialogs/file-save-dialog.c
+++ b/app/dialogs/file-save-dialog.c
@@ -157,7 +157,30 @@ file_save_dialog_response (GtkWidget *save_dialog,
}
else /* GIMP_IS_EXPORT_DIALOG (dialog) */
{
+ GimpExportDialog *export_dialog = GIMP_EXPORT_DIALOG (dialog);
+ gint width = 0.0;
+ gint height = 0.0;
+ GimpUnit unit;
+ gdouble xresolution = 0.0;
+ gdouble yresolution = 0.0;
+ GimpUnit resolution_unit;
+ GimpInterpolationType interpolation;
+
gimp_file_dialog_save_state (dialog, "gimp-file-export-dialog-state");
+
+ gimp_export_dialog_get_dimensions (export_dialog,
+ &width,
+ &height,
+ &unit,
+ &xresolution,
+ &yresolution,
+ &resolution_unit,
+ &interpolation);
+ gimp_image_set_export_dimensions (dialog->image,
+ width, height, unit,
+ xresolution, yresolution,
+ resolution_unit,
+ interpolation);
}
if (response_id != GTK_RESPONSE_OK)
diff --git a/app/file/file-save.c b/app/file/file-save.c
index c17b3d4..ec6414e 100644
--- a/app/file/file-save.c
+++ b/app/file/file-save.c
@@ -34,6 +34,8 @@
#include "core/gimpdocumentlist.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
+#include "core/gimpimage-duplicate.h"
+#include "core/gimpimage-scale.h"
#include "core/gimpimagefile.h"
#include "core/gimpparamspecs.h"
#include "core/gimpprogress.h"
@@ -50,6 +52,9 @@
#include "gimp-intl.h"
+static GimpImage * image_duplicate_for_export (GimpImage *image,
+ GimpProgress *progress);
+
/* public functions */
GimpPDBStatusType
@@ -64,6 +69,7 @@ file_save (Gimp *gimp,
gboolean export_forward,
GError **error)
{
+ GimpImage *export_image = NULL;
GimpDrawable *drawable;
GimpValueArray *return_vals;
GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR;
@@ -90,7 +96,15 @@ file_save (Gimp *gimp,
g_object_ref (image);
g_object_ref (file);
- drawable = gimp_image_get_active_drawable (image);
+ if (export_forward || export_backward)
+ {
+ export_image = image_duplicate_for_export (image, progress);
+ drawable = gimp_image_get_active_drawable (image);
+ }
+ else
+ {
+ drawable = gimp_image_get_active_drawable (image);
+ }
if (! drawable)
goto out;
@@ -168,7 +182,7 @@ file_save (Gimp *gimp,
uri = g_file_get_uri (file);
- image_ID = gimp_image_get_ID (image);
+ image_ID = gimp_image_get_ID (export_image ? export_image : image);
drawable_ID = gimp_item_get_ID (GIMP_ITEM (drawable));
return_vals =
@@ -289,6 +303,74 @@ file_save (Gimp *gimp,
g_free (path);
g_free (uri);
+ if (export_image)
+ g_object_unref (export_image);
return status;
}
+
+/* private functions */
+
+/*
+ * image_duplicate_scale:
+ *
+ * Returns: NULL if the export dimension are the same as the original,
+ * or a duplicate #GimpImage scaled to the new dimensions otherwise.
+ * The duplicate must be freed with g_object_unref(). */
+static GimpImage *
+image_duplicate_for_export (GimpImage *image,
+ GimpProgress *progress)
+{
+ GimpImage *new_image = NULL;
+ /* Current resolution. */
+ gdouble current_xres;
+ gdouble current_yres;
+ /* All export dimensions. */
+ gint width;
+ gint height;
+ GimpUnit unit;
+ gdouble xresolution;
+ gdouble yresolution;
+ GimpUnit resolution_unit;
+ GimpInterpolationType interpolation;
+
+ /* Get current resolution. */
+ gimp_image_get_resolution (image, ¤t_xres, ¤t_yres);
+
+ /* Get export dimensions. */
+ gimp_image_get_export_dimensions (image,
+ &width,
+ &height,
+ &unit,
+ &xresolution,
+ &yresolution,
+ &resolution_unit,
+ &interpolation);
+ if (width > 0 && height > 0)
+ {
+ if (width != gimp_image_get_width (image) ||
+ height != gimp_image_get_height (image) ||
+ xresolution != current_xres ||
+ yresolution != current_yres ||
+ resolution_unit != gimp_image_get_unit (image))
+ {
+ new_image = gimp_image_duplicate (image);
+
+ gimp_image_set_resolution (new_image, xresolution, yresolution);
+ gimp_image_set_unit (new_image, resolution_unit);
+
+ if (width != gimp_image_get_width (image) ||
+ height != gimp_image_get_height (image))
+ {
+ gimp_image_scale (new_image, width, height, interpolation, progress);
+ }
+ }
+ }
+ else
+ {
+ g_warning ("Scale Error: "
+ "Both width and height must be greater than zero.");
+ }
+
+ return new_image;
+}
diff --git a/app/widgets/gimpexportdialog.c b/app/widgets/gimpexportdialog.c
index 897c205..f23566a 100644
--- a/app/widgets/gimpexportdialog.c
+++ b/app/widgets/gimpexportdialog.c
@@ -31,8 +31,15 @@
#include "widgets-types.h"
#include "core/gimp.h"
+#include "core/gimpcontext.h"
#include "core/gimpimage.h"
+#include "config/gimpcoreconfig.h"
+
+#include "display/display-types.h"
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
#include "file/file-utils.h"
#include "file/gimp-file.h"
@@ -43,11 +50,13 @@
#include "gimpexportdialog.h"
#include "gimpfiledialog.h"
#include "gimphelp-ids.h"
+#include "gimpsizebox.h"
#include "gimp-intl.h"
-static GFile * gimp_export_dialog_get_default_folder (Gimp *gimp);
+static void gimp_export_dialog_constructed (GObject *object);
+static GFile * gimp_export_dialog_get_default_folder (Gimp *gimp);
G_DEFINE_TYPE (GimpExportDialog, gimp_export_dialog,
GIMP_TYPE_FILE_DIALOG)
@@ -57,6 +66,9 @@ G_DEFINE_TYPE (GimpExportDialog, gimp_export_dialog,
static void
gimp_export_dialog_class_init (GimpExportDialogClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gimp_export_dialog_constructed;
}
static void
@@ -64,6 +76,49 @@ gimp_export_dialog_init (GimpExportDialog *dialog)
{
}
+static void
+gimp_export_dialog_constructed (GObject *object)
+{
+ GimpExportDialog *dialog = GIMP_EXPORT_DIALOG (object);
+ GtkWidget *frame;
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ dialog->size_expander = gtk_expander_new_with_mnemonic (NULL);
+ gtk_expander_set_label (GTK_EXPANDER (dialog->size_expander),
+ _("Scale Image for Export"));
+
+ dialog->resize_vbox = gtk_vbox_new (FALSE, 2);
+ gtk_container_add (GTK_CONTAINER (dialog->size_expander), dialog->resize_vbox);
+
+ frame = gimp_frame_new (_("Quality"));
+ gtk_box_pack_end (GTK_BOX (dialog->resize_vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_container_add (GTK_CONTAINER (frame), hbox);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new_with_mnemonic (_("I_nterpolation:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ dialog->interpolation_combo = gimp_enum_combo_box_new (GIMP_TYPE_INTERPOLATION_TYPE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->interpolation_combo);
+ gtk_box_pack_start (GTK_BOX (hbox), dialog->interpolation_combo, FALSE, FALSE, 0);
+ gtk_widget_show (dialog->interpolation_combo);
+
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (dialog->interpolation_combo),
+ GIMP_FILE_DIALOG (dialog)->gimp->config->interpolation_type);
+
+ gimp_file_dialog_add_extra_widget (GIMP_FILE_DIALOG (dialog),
+ dialog->size_expander,
+ FALSE, FALSE, 0);
+ gtk_widget_show (dialog->size_expander);
+}
+
/* public functions */
GtkWidget *
@@ -99,10 +154,20 @@ gimp_export_dialog_set_image (GimpExportDialog *dialog,
Gimp *gimp,
GimpImage *image)
{
- GFile *dir_file = NULL;
- GFile *name_file = NULL;
- GFile *ext_file = NULL;
- gchar *basename;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpDisplay *display = gimp_context_get_display (context);
+ GFile *dir_file = NULL;
+ GFile *name_file = NULL;
+ GFile *ext_file = NULL;
+ gchar *basename;
+ gdouble xres, yres;
+ gint export_width;
+ gint export_height;
+ GimpUnit export_unit;
+ gdouble export_xres;
+ gdouble export_yres;
+ GimpUnit export_res_unit;
+ GimpInterpolationType export_interpolation;
g_return_if_fail (GIMP_IS_EXPORT_DIALOG (dialog));
g_return_if_fail (GIMP_IS_IMAGE (image));
@@ -213,6 +278,85 @@ gimp_export_dialog_set_image (GimpExportDialog *dialog,
}
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
+
+ /* Extra feature for resize-on-export:
+ * I have to destroy and recreate the size box because current code does not
+ * behave well if I just reset properties to other values. */
+ if (dialog->size_box)
+ gtk_widget_destroy (dialog->size_box);
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ dialog->size_box = g_object_new (GIMP_TYPE_SIZE_BOX,
+ "width", gimp_image_get_width (image),
+ "height", gimp_image_get_height (image),
+ "unit", (GimpUnit) gimp_display_get_shell (display)->unit,
+ "xresolution", xres,
+ "yresolution", yres,
+ "resolution-unit", gimp_image_get_unit (image),
+ "keep-aspect", TRUE,
+ "edit-resolution", TRUE,
+ NULL);
+ gimp_image_get_export_dimensions (image,
+ &export_width,
+ &export_height,
+ &export_unit,
+ &export_xres,
+ &export_yres,
+ &export_res_unit,
+ &export_interpolation);
+
+ if (export_width != 0 && export_height != 0 &&
+ export_xres != 0 && export_yres != 0 &&
+ (export_width != gimp_image_get_width (image) ||
+ export_height != gimp_image_get_height (image) ||
+ export_xres != xres || export_yres != yres ||
+ export_res_unit != gimp_image_get_unit (image)))
+ {
+ /* Some values have been previously set. Keep them! */
+ gimp_size_box_set_size (GIMP_SIZE_BOX (dialog->size_box),
+ export_width,
+ export_height,
+ export_unit);
+ gimp_size_box_set_resolution (GIMP_SIZE_BOX (dialog->size_box),
+ export_xres,
+ export_yres,
+ export_res_unit);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (dialog->interpolation_combo),
+ export_interpolation);
+ gtk_expander_set_expanded (GTK_EXPANDER (dialog->size_expander),
+ TRUE);
+ }
+ else
+ {
+ gtk_expander_set_expanded (GTK_EXPANDER (dialog->size_expander),
+ FALSE);
+ }
+ gtk_box_pack_start (GTK_BOX (dialog->resize_vbox), dialog->size_box,
+ FALSE, FALSE, 0);
+ gtk_widget_show_all (dialog->resize_vbox);
+}
+
+void
+gimp_export_dialog_get_dimensions (GimpExportDialog *dialog,
+ gint *width,
+ gint *height,
+ GimpUnit *unit,
+ gdouble *xresolution,
+ gdouble *yresolution,
+ GimpUnit *resolution_unit,
+ GimpInterpolationType *interpolation)
+{
+ g_object_get (dialog->size_box,
+ "width", width,
+ "height", height,
+ "unit", unit,
+ "xresolution", xresolution,
+ "yresolution", yresolution,
+ "resolution-unit", resolution_unit,
+ NULL);
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (dialog->interpolation_combo),
+ (gint *) interpolation);
}
/* private functions */
diff --git a/app/widgets/gimpexportdialog.h b/app/widgets/gimpexportdialog.h
index 1280c74..e3c3dfa 100644
--- a/app/widgets/gimpexportdialog.h
+++ b/app/widgets/gimpexportdialog.h
@@ -38,6 +38,11 @@ typedef struct _GimpExportDialogClass GimpExportDialogClass;
struct _GimpExportDialog
{
GimpFileDialog parent_instance;
+
+ GtkWidget *size_expander;
+ GtkWidget *resize_vbox;
+ GtkWidget *size_box;
+ GtkWidget *interpolation_combo;
};
struct _GimpExportDialogClass
@@ -48,11 +53,19 @@ struct _GimpExportDialogClass
GType gimp_export_dialog_get_type (void) G_GNUC_CONST;
-GtkWidget * gimp_export_dialog_new (Gimp *gimp);
+GtkWidget * gimp_export_dialog_new (Gimp *gimp);
void gimp_export_dialog_set_image (GimpExportDialog *dialog,
Gimp *gimp,
GimpImage *image);
+void gimp_export_dialog_get_dimensions (GimpExportDialog *dialog,
+ gint *width,
+ gint *height,
+ GimpUnit *unit,
+ gdouble *xresolution,
+ gdouble *yresolution,
+ GimpUnit *resolution_unit,
+ GimpInterpolationType *interpolation);
G_END_DECLS
diff --git a/app/widgets/gimpsizebox.c b/app/widgets/gimpsizebox.c
index 57bb231..c6e147f 100644
--- a/app/widgets/gimpsizebox.c
+++ b/app/widgets/gimpsizebox.c
@@ -61,7 +61,9 @@ typedef struct _GimpSizeBoxPrivate GimpSizeBoxPrivate;
struct _GimpSizeBoxPrivate
{
GimpSizeEntry *size_entry;
+ GimpSizeEntry *resolution_entry;
GimpChainButton *size_chain;
+ GimpChainButton *resolution_chain;
GtkWidget *pixel_label;
GtkWidget *res_label;
};
@@ -263,7 +265,8 @@ gimp_size_box_constructed (GObject *object)
_("_Y resolution:"),
box->yresolution, 1.0,
1, 1, 1, 10);
-
+ priv->resolution_entry = GIMP_SIZE_ENTRY (entry);
+ priv->resolution_chain = GIMP_COORDINATES_CHAINBUTTON (GIMP_SIZE_ENTRY (entry));
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_widget_show (entry);
@@ -422,6 +425,66 @@ gimp_size_box_get_property (GObject *object,
}
}
+/**
+ * gimp_size_box_set_size:
+ * @width: width in pixels.
+ * @height: height in pixels.
+ * @unit: #GimpUnit for @width and @height display.
+ *
+ * Sets the value for width and height. These are different from the
+ * initial values set through properties (which determined the ratio
+ * and "100%" values for instance).
+ */
+void
+gimp_size_box_set_size (GimpSizeBox *box,
+ gint width,
+ gint height,
+ GimpUnit unit)
+{
+ GimpSizeBoxPrivate *priv = GIMP_SIZE_BOX_GET_PRIVATE (box);
+
+ /* gimp_size_entry_set_value() depends on the unit. So I set
+ * the pixel unit first since I always want to work with pixels. */
+ gimp_size_entry_set_unit (priv->size_entry, GIMP_UNIT_PIXEL);
+ gimp_size_entry_set_value (priv->size_entry, 0, width);
+ if (gimp_size_entry_get_value (priv->size_entry, 1) != height)
+ {
+ gimp_chain_button_set_active (priv->size_chain,
+ FALSE);
+ gimp_size_entry_set_value (priv->size_entry, 1, height);
+ }
+ gimp_size_entry_set_unit (priv->size_entry, unit);
+}
+
+/**
+ * gimp_size_box_set_resolution:
+ * @xres: X-resolution in ppi.
+ * @yres: Y-resolution in ppi.
+ * @unit: #GimpUnit for @xres and @xres display.
+ *
+ * Sets the resolution.
+ */
+void
+gimp_size_box_set_resolution (GimpSizeBox *box,
+ gdouble xres,
+ gdouble yres,
+ GimpUnit unit)
+{
+ GimpSizeBoxPrivate *priv = GIMP_SIZE_BOX_GET_PRIVATE (box);
+
+ g_return_if_fail (box->edit_resolution);
+
+ gimp_size_entry_set_unit (priv->resolution_entry, GIMP_UNIT_INCH);
+ gimp_size_entry_set_value (priv->resolution_entry, 0, xres);
+ if (gimp_size_entry_get_value (priv->resolution_entry, 1) != yres)
+ {
+ gimp_chain_button_set_active (priv->resolution_chain,
+ FALSE);
+ gimp_size_entry_set_value (priv->resolution_entry, 1, yres);
+ }
+ gimp_size_entry_set_unit (priv->resolution_entry, unit);
+}
+
static void
gimp_size_box_update_size (GimpSizeBox *box)
{
diff --git a/app/widgets/gimpsizebox.h b/app/widgets/gimpsizebox.h
index b3de8e1..263b35c 100644
--- a/app/widgets/gimpsizebox.h
+++ b/app/widgets/gimpsizebox.h
@@ -58,6 +58,14 @@ struct _GimpSizeBoxClass
GType gimp_size_box_get_type (void) G_GNUC_CONST;
+void gimp_size_box_set_size (GimpSizeBox *box,
+ gint width,
+ gint height,
+ GimpUnit unit);
+void gimp_size_box_set_resolution (GimpSizeBox *box,
+ gdouble xres,
+ gdouble yres,
+ GimpUnit unit);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]