[gimp] app: add interpolation, abyss policy, and high quality preview options ...
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add interpolation, abyss policy, and high quality preview options ...
- Date: Fri, 19 May 2017 22:30:18 +0000 (UTC)
commit f400bdc04924952abdd19418ef95a690676eb81b
Author: Ell <ell_se yahoo com>
Date: Fri May 19 18:14:45 2017 -0400
app: add interpolation, abyss policy, and high quality preview options ...
... to the warp tool
The interpolation and abyss policy options control the sampler type
and abyss policy of the map-relative node. The high quality preview
option determines whether to use the same sampler for map-relative
during preview as the one used during commit, or whether to use a
fast nearest-neighbor sampler.
A bit too much? Maybe :)
app/tools/gimpwarpoptions.c | 63 +++++++++++++++++++-
app/tools/gimpwarpoptions.h | 25 ++++----
app/tools/gimpwarptool.c | 138 ++++++++++++++++++++++++++++++++++---------
3 files changed, 185 insertions(+), 41 deletions(-)
---
diff --git a/app/tools/gimpwarpoptions.c b/app/tools/gimpwarpoptions.c
index 1f87a43..9230c3d 100644
--- a/app/tools/gimpwarpoptions.c
+++ b/app/tools/gimpwarpoptions.c
@@ -44,6 +44,9 @@ enum
PROP_EFFECT_HARDNESS,
PROP_EFFECT_STRENGTH,
PROP_STROKE_SPACING,
+ PROP_INTERPOLATION,
+ PROP_ABYSS_POLICY,
+ PROP_HIGH_QUALITY_PREVIEW,
PROP_STROKE_DURING_MOTION,
PROP_STROKE_PERIODICALLY,
PROP_STROKE_PERIODICALLY_RATE,
@@ -111,6 +114,29 @@ gimp_warp_options_class_init (GimpWarpOptionsClass *klass)
1.0, 100.0, 20.0,
GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_INTERPOLATION,
+ "interpolation",
+ _("Interpolation"),
+ _("Interpolation method"),
+ GIMP_TYPE_INTERPOLATION_TYPE,
+ GIMP_INTERPOLATION_CUBIC,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_ABYSS_POLICY,
+ "abyss-policy",
+ _("Abyss policy"),
+ _("Out-of-bounds sampling behavior"),
+ GEGL_TYPE_ABYSS_POLICY,
+ GEGL_ABYSS_NONE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_HIGH_QUALITY_PREVIEW,
+ "high-quality-preview",
+ _("High quality preview"),
+ _("Use an accurate but slower preview"),
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
+
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_STROKE_DURING_MOTION,
"stroke-during-motion",
_("During motion"),
@@ -128,7 +154,7 @@ gimp_warp_options_class_init (GimpWarpOptionsClass *klass)
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_PERIODICALLY_RATE,
"stroke-periodically-rate",
_("Rate"),
- _("Periodical stroke rate"),
+ _("Periodic stroke rate"),
0.0, 100.0, 50.0,
GIMP_PARAM_STATIC_STRINGS);
@@ -170,6 +196,15 @@ gimp_warp_options_set_property (GObject *object,
case PROP_STROKE_SPACING:
options->stroke_spacing = g_value_get_double (value);
break;
+ case PROP_INTERPOLATION:
+ options->interpolation = g_value_get_enum (value);
+ break;
+ case PROP_ABYSS_POLICY:
+ options->abyss_policy = g_value_get_enum (value);
+ break;
+ case PROP_HIGH_QUALITY_PREVIEW:
+ options->high_quality_preview = g_value_get_boolean (value);
+ break;
case PROP_STROKE_DURING_MOTION:
options->stroke_during_motion = g_value_get_boolean (value);
break;
@@ -214,6 +249,15 @@ gimp_warp_options_get_property (GObject *object,
case PROP_STROKE_SPACING:
g_value_set_double (value, options->stroke_spacing);
break;
+ case PROP_INTERPOLATION:
+ g_value_set_enum (value, options->interpolation);
+ break;
+ case PROP_ABYSS_POLICY:
+ g_value_set_enum (value, options->abyss_policy);
+ break;
+ case PROP_HIGH_QUALITY_PREVIEW:
+ g_value_set_boolean (value, options->high_quality_preview);
+ break;
case PROP_STROKE_DURING_MOTION:
g_value_set_boolean (value, options->stroke_during_motion);
break;
@@ -274,6 +318,23 @@ gimp_warp_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
gtk_widget_show (scale);
+ combo = gimp_prop_enum_combo_box_new (config, "interpolation", 0, 0);
+ gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Interpolation"));
+ g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+ gtk_widget_show (combo);
+
+ combo = gimp_prop_enum_combo_box_new (config, "abyss-policy",
+ GEGL_ABYSS_NONE, GEGL_ABYSS_LOOP);
+ gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Abyss policy"));
+ g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+ gtk_widget_show (combo);
+
+ button = gimp_prop_check_button_new (config, "high-quality-preview", NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
/* the stroke frame */
frame = gimp_frame_new (_("Stroke"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
diff --git a/app/tools/gimpwarpoptions.h b/app/tools/gimpwarpoptions.h
index 9d143d7..af9ad4a 100644
--- a/app/tools/gimpwarpoptions.h
+++ b/app/tools/gimpwarpoptions.h
@@ -37,22 +37,25 @@ typedef struct _GimpWarpOptionsClass GimpWarpOptionsClass;
struct _GimpWarpOptions
{
- GimpToolOptions parent_instance;
+ GimpToolOptions parent_instance;
- GimpWarpBehavior behavior;
- gdouble effect_size;
- gdouble effect_hardness;
- gdouble effect_strength;
- gdouble stroke_spacing;
+ GimpWarpBehavior behavior;
+ gdouble effect_size;
+ gdouble effect_hardness;
+ gdouble effect_strength;
+ gdouble stroke_spacing;
+ GimpInterpolationType interpolation;
+ GeglAbyssPolicy abyss_policy;
+ gboolean high_quality_preview;
- gboolean stroke_during_motion;
- gboolean stroke_periodically;
- gdouble stroke_periodically_rate;
+ gboolean stroke_during_motion;
+ gboolean stroke_periodically;
+ gdouble stroke_periodically_rate;
- gint n_animation_frames;
+ gint n_animation_frames;
/* options gui */
- GtkWidget *animate_button;
+ GtkWidget *animate_button;
};
struct _GimpWarpOptionsClass
diff --git a/app/tools/gimpwarptool.c b/app/tools/gimpwarptool.c
index 4cdf358..d2d6179 100644
--- a/app/tools/gimpwarptool.c
+++ b/app/tools/gimpwarptool.c
@@ -54,7 +54,6 @@
#define STROKE_TIMER_MAX_FPS 20
#define PREVIEW_SAMPLER GEGL_SAMPLER_NEAREST
-#define COMMIT_SAMPLER GEGL_SAMPLER_CUBIC
static void gimp_warp_tool_control (GimpTool *tool,
@@ -119,6 +118,10 @@ static gboolean gimp_warp_tool_stroke_timer (GimpWarpTool *wt);
static void gimp_warp_tool_create_graph (GimpWarpTool *wt);
static void gimp_warp_tool_create_filter (GimpWarpTool *wt,
GimpDrawable *drawable);
+static void gimp_warp_tool_set_sampler (GimpWarpTool *wt,
+ gboolean commit);
+static GeglRectangle
+ gimp_warp_tool_get_stroke_bounds (GeglNode *node);
static void gimp_warp_tool_update_stroke (GimpWarpTool *wt,
GeglNode *node);
static void gimp_warp_tool_stroke_changed (GeglPath *stroke,
@@ -555,6 +558,9 @@ gimp_warp_tool_options_notify (GimpTool *tool,
GimpToolOptions *options,
const GParamSpec *pspec)
{
+ GimpWarpTool *wt = GIMP_WARP_TOOL (tool);
+ GimpWarpOptions *wt_options = GIMP_WARP_OPTIONS (options);
+
GIMP_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
if (! strcmp (pspec->name, "effect-size"))
@@ -562,6 +568,32 @@ gimp_warp_tool_options_notify (GimpTool *tool,
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
+ else if (! strcmp (pspec->name, "interpolation"))
+ {
+ if (wt_options->high_quality_preview)
+ {
+ gimp_warp_tool_set_sampler (wt, /* commit = */ FALSE);
+
+ gimp_warp_tool_update_stroke (wt, NULL);
+ }
+ }
+ else if (! strcmp (pspec->name, "abyss-policy"))
+ {
+ if (wt->render_node)
+ {
+ gegl_node_set (wt->render_node,
+ "abyss-policy", wt_options->abyss_policy,
+ NULL);
+
+ gimp_warp_tool_update_stroke (wt, NULL);
+ }
+ }
+ else if (! strcmp (pspec->name, "high-quality-preview"))
+ {
+ gimp_warp_tool_set_sampler (wt, /* commit = */ FALSE);
+
+ gimp_warp_tool_update_stroke (wt, NULL);
+ }
}
static void
@@ -743,12 +775,7 @@ gimp_warp_tool_commit (GimpWarpTool *wt)
{
gimp_tool_control_push_preserve (tool->control, TRUE);
- if (COMMIT_SAMPLER != PREVIEW_SAMPLER)
- {
- gegl_node_set (wt->render_node,
- "sampler-type", COMMIT_SAMPLER,
- NULL);
- }
+ gimp_warp_tool_set_sampler (wt, /* commit = */ TRUE);
gimp_drawable_filter_commit (wt->filter, GIMP_PROGRESS (tool), FALSE);
g_object_unref (wt->filter);
@@ -808,9 +835,10 @@ gimp_warp_tool_stroke_timer (GimpWarpTool *wt)
static void
gimp_warp_tool_create_graph (GimpWarpTool *wt)
{
- GeglNode *graph; /* Wraper to be returned */
- GeglNode *input, *output; /* Proxy nodes */
- GeglNode *coords, *render; /* Render nodes */
+ GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt);
+ GeglNode *graph; /* Wraper to be returned */
+ GeglNode *input, *output; /* Proxy nodes */
+ GeglNode *coords, *render; /* Render nodes */
/* render_node is not supposed to be recreated */
g_return_if_fail (wt->graph == NULL);
@@ -827,7 +855,7 @@ gimp_warp_tool_create_graph (GimpWarpTool *wt)
render = gegl_node_new_child (graph,
"operation", "gegl:map-relative",
- "sampler-type", PREVIEW_SAMPLER,
+ "abyss-policy", options->abyss_policy,
NULL);
gegl_node_connect_to (input, "output",
@@ -850,12 +878,7 @@ gimp_warp_tool_create_filter (GimpWarpTool *wt,
if (! wt->graph)
gimp_warp_tool_create_graph (wt);
- if (PREVIEW_SAMPLER != COMMIT_SAMPLER)
- {
- gegl_node_set (wt->render_node,
- "sampler-type", PREVIEW_SAMPLER,
- NULL);
- }
+ gimp_warp_tool_set_sampler (wt, /* commit = */ FALSE);
wt->filter = gimp_drawable_filter_new (drawable,
_("Warp transform"),
@@ -874,11 +897,39 @@ gimp_warp_tool_create_filter (GimpWarpTool *wt,
}
static void
-gimp_warp_tool_update_stroke (GimpWarpTool *wt,
- GeglNode *node)
+gimp_warp_tool_set_sampler (GimpWarpTool *wt,
+ gboolean commit)
{
- GeglPath *stroke;
- gdouble size;
+ GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt);
+ GeglSamplerType sampler;
+ GeglSamplerType old_sampler;
+
+ if (! wt->render_node)
+ return;
+
+ if (commit || options->high_quality_preview)
+ sampler = (GeglSamplerType) options->interpolation;
+ else
+ sampler = PREVIEW_SAMPLER;
+
+ gegl_node_get (wt->render_node,
+ "sampler-type", &old_sampler,
+ NULL);
+
+ if (sampler != old_sampler)
+ {
+ gegl_node_set (wt->render_node,
+ "sampler-type", sampler,
+ NULL);
+ }
+}
+
+static GeglRectangle
+gimp_warp_tool_get_stroke_bounds (GeglNode *node)
+{
+ GeglRectangle bbox = {0, 0, 0, 0};
+ GeglPath *stroke;
+ gdouble size;
gegl_node_get (node,
"stroke", &stroke,
@@ -891,7 +942,6 @@ gimp_warp_tool_update_stroke (GimpWarpTool *wt,
gdouble max_x;
gdouble min_y;
gdouble max_y;
- GeglRectangle bbox;
gegl_path_get_bounds (stroke, &min_x, &max_x, &min_y, &max_y);
g_object_unref (stroke);
@@ -900,7 +950,42 @@ gimp_warp_tool_update_stroke (GimpWarpTool *wt,
bbox.y = floor (min_y - size * 0.5);
bbox.width = ceil (max_x + size * 0.5) - bbox.x;
bbox.height = ceil (max_y + size * 0.5) - bbox.y;
+ }
+
+ return bbox;
+}
+
+static void
+gimp_warp_tool_update_stroke (GimpWarpTool *wt,
+ GeglNode *node)
+{
+ GeglRectangle bbox = {0, 0, 0, 0};
+ if (! wt->filter)
+ return;
+
+ if (node)
+ {
+ /* update just this stroke */
+ bbox = gimp_warp_tool_get_stroke_bounds (node);
+ }
+ else if (wt->render_node)
+ {
+ /* update all strokes */
+ for (node = gegl_node_get_producer (wt->render_node, "aux", NULL);
+ ! strcmp (gegl_node_get_operation (node), "gegl:warp");
+ node = gegl_node_get_producer (node, "input", NULL))
+ {
+ GeglRectangle node_bbox;
+
+ node_bbox = gimp_warp_tool_get_stroke_bounds (node);
+
+ gegl_rectangle_bounding_box (&bbox, &bbox, &node_bbox);
+ }
+ }
+
+ if (! gegl_rectangle_is_empty (&bbox))
+ {
#ifdef WARP_DEBUG
g_printerr ("update stroke: (%d,%d), %dx%d\n",
bbox.x, bbox.y,
@@ -1021,12 +1106,7 @@ gimp_warp_tool_animate (GimpWarpTool *wt)
wt->filter = NULL;
}
- if (COMMIT_SAMPLER != PREVIEW_SAMPLER)
- {
- gegl_node_set (wt->render_node,
- "sampler-type", COMMIT_SAMPLER,
- NULL);
- }
+ gimp_warp_tool_set_sampler (wt, /* commit = */ TRUE);
gimp_progress_start (GIMP_PROGRESS (tool), FALSE,
_("Rendering Frame %d"), 1);
@@ -1098,7 +1178,7 @@ gimp_warp_tool_animate (GimpWarpTool *wt)
/* recreate the image map */
gimp_warp_tool_create_filter (wt, tool->drawable);
- gimp_drawable_filter_apply (wt->filter, NULL);
+ gimp_warp_tool_update_stroke (wt, NULL);
widget = GTK_WIDGET (gimp_display_get_shell (tool->display));
gimp_create_display (orig_image->gimp, image, GIMP_UNIT_PIXEL, 1.0,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]