[gimp/soc-2011-seamless-clone2] app: port the foreground select tool to the GEGL matting ops
- From: Clayton Walker <claytonw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2011-seamless-clone2] app: port the foreground select tool to the GEGL matting ops
- Date: Wed, 8 May 2013 15:23:32 +0000 (UTC)
commit 786759d543cbc5e261e41bb92ba24f6ef43696aa
Author: Miroslav Talasek <miroslav talasek seznam cz>
Date: Wed May 8 00:00:48 2013 +0200
app: port the foreground select tool to the GEGL matting ops
This is work in progress and needs the fixed GEGL ops too.
app/tools/gimpforegroundselectoptions.c | 429 ++++++++++++-----------
app/tools/gimpforegroundselectoptions.h | 36 ++-
app/tools/gimpforegroundselecttool.c | 577 ++++++++++++++++---------------
app/tools/gimpforegroundselecttool.h | 19 +-
4 files changed, 558 insertions(+), 503 deletions(-)
---
diff --git a/app/tools/gimpforegroundselectoptions.c b/app/tools/gimpforegroundselectoptions.c
index 474da98..6591bc2 100644
--- a/app/tools/gimpforegroundselectoptions.c
+++ b/app/tools/gimpforegroundselectoptions.c
@@ -26,10 +26,9 @@
#include "tools-types.h"
-#if 0
-#include "base/siox.h"
-#endif
-
+#include "widgets/gimppropwidgets.h"
+#include "widgets/gimpspinscale.h"
+#include "widgets/gimpwidgets-constructors.h"
#include "widgets/gimpwidgets-utils.h"
#include "gimpforegroundselectoptions.h"
@@ -38,22 +37,26 @@
#include "gimp-intl.h"
+/*
+ * for matting-global: iterations int
+ * for matting-levin: levels int, active levels int
+ */
+
enum
{
PROP_0,
- PROP_ANTIALIAS,
- PROP_CONTIGUOUS,
- PROP_BACKGROUND,
+ PROP_DRAW_MODE,
PROP_STROKE_WIDTH,
- PROP_SMOOTHNESS,
PROP_MASK_COLOR,
- PROP_EXPANDED,
- PROP_SENSITIVITY_L,
- PROP_SENSITIVITY_A,
- PROP_SENSITIVITY_B
+ PROP_ENGINE,
+ PROP_ITERATIONS,
+ PROP_LEVELS,
+ PROP_ACTIVE_LEVELS
};
+
+
static void gimp_foreground_select_options_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -63,6 +66,14 @@ static void gimp_foreground_select_options_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
+static void gimp_foreground_select_options_gui_reset_stroke_width (GtkWidget *button,
+ GimpToolOptions *tool_options);
+
+
+static void gimp_foreground_select_notify_engine (GimpToolOptions *tool_options,
+ GParamSpec *pspec,
+ GtkWidget *table);
+
G_DEFINE_TYPE (GimpForegroundSelectOptions, gimp_foreground_select_options,
GIMP_TYPE_SELECTION_OPTIONS)
@@ -77,40 +88,27 @@ gimp_foreground_select_options_class_init (GimpForegroundSelectOptionsClass *kla
object_class->get_property = gimp_foreground_select_options_get_property;
/* override the antialias default value from GimpSelectionOptions */
- GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ANTIALIAS,
- "antialias",
- N_("Smooth edges"),
- FALSE,
- GIMP_PARAM_STATIC_STRINGS);
-
- GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_CONTIGUOUS,
- "contiguous",
- N_("Select a single contiguous area"),
- TRUE,
- GIMP_PARAM_STATIC_STRINGS);
-
- GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_BACKGROUND,
- "background",
- N_("Paint over areas to mark color values for "
- "inclusion or exclusion from selection"),
- FALSE,
- GIMP_PARAM_STATIC_STRINGS);
-
- GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_STROKE_WIDTH,
- "stroke-width",
- N_("Size of the brush used for refinements"),
- 1, 80, 18,
- GIMP_PARAM_STATIC_STRINGS);
-
-#if 0
- GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_SMOOTHNESS,
- "smoothness",
- N_("Smaller values give a more accurate "
- "selection border but may introduce holes "
- "in the selection"),
- 0, 8, SIOX_DEFAULT_SMOOTHNESS,
- GIMP_PARAM_STATIC_STRINGS);
-#endif
+
+ GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_DRAW_MODE,
+ "draw-mode",
+ N_("Paint over areas to mark color values for "
+ "inclusion or exclusion from selection"),
+ GIMP_TYPE_MATTING_DRAW_MODE,
+ GIMP_MATTING_DRAW_MODE_FOREGROUND,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_ENGINE,
+ "engine",
+ N_("Matting engine to use"),
+ GIMP_TYPE_MATTING_ENGINE,
+ GIMP_MATTING_ENGINE_MATTING_GLOBAL,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_STROKE_WIDTH,
+ "stroke-width",
+ N_("Size of the brush used for refinements"),
+ 1, 6000, 10,
+ GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_MASK_COLOR,
"mask-color",
@@ -119,30 +117,21 @@ gimp_foreground_select_options_class_init (GimpForegroundSelectOptionsClass *kla
GIMP_BLUE_CHANNEL,
GIMP_PARAM_STATIC_STRINGS);
- GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_EXPANDED,
- "expanded", NULL,
- FALSE,
- 0);
-
-#if 0
- GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SENSITIVITY_L,
- "sensitivity-l",
- N_("Sensitivity for brightness component"),
- 0.0, 10.0, SIOX_DEFAULT_SENSITIVITY_L,
- GIMP_PARAM_STATIC_STRINGS);
-
- GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SENSITIVITY_A,
- "sensitivity-a",
- N_("Sensitivity for red/green component"),
- 0.0, 10.0, SIOX_DEFAULT_SENSITIVITY_A,
- GIMP_PARAM_STATIC_STRINGS);
-
- GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_SENSITIVITY_B,
- "sensitivity-b",
- N_("Sensitivity for yellow/blue component"),
- 0.0, 10.0, SIOX_DEFAULT_SENSITIVITY_B,
- GIMP_PARAM_STATIC_STRINGS);
-#endif
+ GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_LEVELS,
+ "levels",
+ N_("Parameter for matting-levin"),
+ 1, 10, 2,
+ GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_ACTIVE_LEVELS,
+ "active-levels",
+ N_("Parameter for matting-levin"),
+ 1, 10, 2,
+ GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_ITERATIONS,
+ "iterations",
+ N_("Parameter for matting-global"),
+ 1, 10, 2,
+ GIMP_PARAM_STATIC_STRINGS);
}
static void
@@ -159,51 +148,39 @@ gimp_foreground_select_options_set_property (GObject *object,
GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_OPTIONS (object);
switch (property_id)
- {
- case PROP_ANTIALIAS:
- GIMP_SELECTION_OPTIONS (object)->antialias = g_value_get_boolean (value);
+ {
+ case PROP_DRAW_MODE:
+ options->draw_mode = g_value_get_enum (value);
break;
- case PROP_CONTIGUOUS:
- options->contiguous = g_value_get_boolean (value);
- break;
-
- case PROP_BACKGROUND:
- options->background = g_value_get_boolean (value);
+ case PROP_ENGINE:
+ options->engine = g_value_get_enum (value);
break;
case PROP_STROKE_WIDTH:
options->stroke_width = g_value_get_int (value);
break;
- case PROP_SMOOTHNESS:
- options->smoothness = g_value_get_int (value);
- break;
-
case PROP_MASK_COLOR:
options->mask_color = g_value_get_enum (value);
break;
- case PROP_EXPANDED:
- options->expanded = g_value_get_boolean (value);
- break;
-
- case PROP_SENSITIVITY_L:
- options->sensitivity[0] = g_value_get_double (value);
+ case PROP_LEVELS:
+ options->levels = g_value_get_int (value);
break;
- case PROP_SENSITIVITY_A:
- options->sensitivity[1] = g_value_get_double (value);
+ case PROP_ACTIVE_LEVELS:
+ options->active_levels = g_value_get_int (value);
break;
- case PROP_SENSITIVITY_B:
- options->sensitivity[2] = g_value_get_double (value);
+ case PROP_ITERATIONS:
+ options->iterations = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
- }
+ }
}
static void
@@ -215,51 +192,40 @@ gimp_foreground_select_options_get_property (GObject *object,
GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_OPTIONS (object);
switch (property_id)
- {
- case PROP_ANTIALIAS:
- g_value_set_boolean (value, GIMP_SELECTION_OPTIONS (object)->antialias);
- break;
+ {
- case PROP_CONTIGUOUS:
- g_value_set_boolean (value, options->contiguous);
+ case PROP_DRAW_MODE:
+ g_value_set_enum (value, options->draw_mode);
break;
- case PROP_BACKGROUND:
- g_value_set_boolean (value, options->background);
+ case PROP_ENGINE:
+ g_value_set_enum (value, options->engine);
break;
case PROP_STROKE_WIDTH:
g_value_set_int (value, options->stroke_width);
break;
- case PROP_SMOOTHNESS:
- g_value_set_int (value, options->smoothness);
- break;
-
case PROP_MASK_COLOR:
g_value_set_enum (value, options->mask_color);
break;
- case PROP_EXPANDED:
- g_value_set_boolean (value, options->expanded);
+ case PROP_LEVELS:
+ g_value_set_int (value, options->levels);
break;
- case PROP_SENSITIVITY_L:
- g_value_set_double (value, options->sensitivity[0]);
+ case PROP_ACTIVE_LEVELS:
+ g_value_set_int (value, options->active_levels);
break;
- case PROP_SENSITIVITY_A:
- g_value_set_double (value, options->sensitivity[1]);
- break;
-
- case PROP_SENSITIVITY_B:
- g_value_set_double (value, options->sensitivity[2]);
+ case PROP_ITERATIONS:
+ g_value_set_int (value, options->iterations);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
- }
+ }
}
GtkWidget *
@@ -271,114 +237,173 @@ gimp_foreground_select_options_gui (GimpToolOptions *tool_options)
GtkWidget *button;
GtkWidget *frame;
GtkWidget *scale;
- GtkWidget *label;
- GtkWidget *menu;
- GtkWidget *inner_frame;
+ GtkWidget *combo;
GtkWidget *table;
- gchar *title;
gint row = 0;
- GdkModifierType toggle_mask;
+ GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_OPTIONS (config);
- toggle_mask = gimp_get_toggle_behavior_mask ();
+ frame = gimp_prop_enum_radio_frame_new (config, "draw-mode", _("Draw Mode"),
+ 0,0);
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
- gtk_widget_set_sensitive (GIMP_SELECTION_OPTIONS (tool_options)->antialias_toggle,
- FALSE);
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
- /* single / multiple objects */
- button = gimp_prop_check_button_new (config, "contiguous", _("Contiguous"));
- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+ /* stroke width */
+ scale = gimp_prop_spin_scale_new (config, "stroke-width",
+ _("Stroke width"),
+ 1.0, 10.0, 2);
+ gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (scale), 1.0, 1000.0);
+ gimp_spin_scale_set_gamma (GIMP_SPIN_SCALE (scale), 1.7);
+ gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+ gtk_widget_show (scale);
+
+ button = gimp_stock_button_new (GIMP_STOCK_RESET, NULL);
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_image_set_from_stock (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (button))),
+ GIMP_STOCK_RESET, GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
- /* foreground / background */
- title = g_strdup_printf (_("Interactive refinement (%s)"),
- gimp_get_mod_string (toggle_mask));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (gimp_foreground_select_options_gui_reset_stroke_width),
+ tool_options);
- frame = gimp_prop_boolean_radio_frame_new (config, "background", title,
- _("Mark background"),
- _("Mark foreground"));
- g_free (title);
+ gimp_help_set_help_data (button,
+ _("Reset stroke width native size"), NULL);
+ /* mask color */
+ frame = gimp_frame_new (_("Preview color:"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
- /* stroke width */
- inner_frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (gtk_bin_get_child (GTK_BIN (frame))),
- inner_frame, FALSE, FALSE, 2);
- gtk_widget_show (inner_frame);
+ combo = gimp_prop_enum_combo_box_new (config, "mask-color",
+ GIMP_RED_CHANNEL, GIMP_GRAY_CHANNEL);
+ gtk_container_add (GTK_CONTAINER (frame), combo);
+ gtk_widget_show (combo);
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- gtk_box_pack_start (GTK_BOX (inner_frame), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
+ /* engine */
+ frame = gimp_frame_new (_("Engine:"));
+ gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
- label = gtk_label_new (_("Small brush"));
- gimp_label_set_attributes (GTK_LABEL (label),
- PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
- PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
- -1);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
+ combo = gimp_prop_enum_combo_box_new (config, "engine", 0, 0);
+ gtk_container_add (GTK_CONTAINER (frame), combo);
+ gtk_widget_show (combo);
- label = gtk_label_new (_("Large brush"));
- gimp_label_set_attributes (GTK_LABEL (label),
- PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
- PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
- -1);
- gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
- scale = gimp_prop_hscale_new (config, "stroke-width", 1.0, 5.0, 0);
- gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
- gtk_box_pack_start (GTK_BOX (inner_frame), scale, FALSE, FALSE, 0);
- gtk_widget_show (scale);
+ /* parameters */
- /* smoothness */
- table = gtk_table_new (2, 3, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+ table = gtk_table_new (3, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 2);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
-#if 0
- scale = gimp_prop_hscale_new (config, "smoothness", 0.1, 1.0, 0);
- gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_RIGHT);
- gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
- _("Smoothing:"), 0.0, 0.5, scale, 2, FALSE);
-#endif
+ options->dynamic_widgets.levels = (GObject *)
+ gimp_prop_scale_entry_new (config, "levels",
+ GTK_TABLE (table), 0, row++,
+ "Levels", 1, 1, 0, FALSE, 0, 0);
- /* mask color */
- menu = gimp_prop_enum_combo_box_new (config, "mask-color",
- GIMP_RED_CHANNEL, GIMP_BLUE_CHANNEL);
- gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
- _("Preview color:"), 0.0, 0.5, menu, 2, FALSE);
-
-#if 0
- /* granularity */
- frame = gimp_prop_expander_new (config, "expanded", _("Color Sensitivity"));
- gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
- gtk_widget_show (frame);
+ options->dynamic_widgets.active_levels = (GObject *)
+ gimp_prop_scale_entry_new (config, "active-levels",
+ GTK_TABLE (table), 0, row++,
+ "Act. Levels", 1, 1, 0, FALSE, 0, 0);
- inner_frame = gimp_frame_new ("<expander>");
- gtk_container_add (GTK_CONTAINER (frame), inner_frame);
- gtk_widget_show (inner_frame);
+ options->dynamic_widgets.iterations = (GObject *)
+ gimp_prop_scale_entry_new (config, "iterations",
+ GTK_TABLE (table), 0, row++,
+ "Iterations", 1, 1, 0, FALSE, 0, 0);
- table = gtk_table_new (3, 3, FALSE);
- gtk_table_set_col_spacings (GTK_TABLE (table), 2);
- gtk_table_set_row_spacings (GTK_TABLE (table), 2);
- gtk_container_add (GTK_CONTAINER (inner_frame), table);
- gtk_widget_show (table);
+ g_signal_connect_object (config, "notify::engine",
+ G_CALLBACK (gimp_foreground_select_notify_engine),
+ NULL, 0);
+ gimp_foreground_select_notify_engine (tool_options, NULL, NULL);
- gimp_prop_opacity_entry_new (config, "sensitivity-l",
- GTK_TABLE (table), 0, row++, "L");
+ return vbox;
+}
- gimp_prop_opacity_entry_new (config, "sensitivity-a",
- GTK_TABLE (table), 0, row++, "a");
+static void
+gimp_foreground_select_options_gui_reset_stroke_width (GtkWidget *button,
+ GimpToolOptions *tool_options)
+{
+ g_object_set (tool_options, "stroke-width", 10, NULL);
+}
+
+static void
+gimp_foreground_select_show_scale (GObject *object)
+{
+ GtkWidget *spin;
+ GtkWidget *label;
+ GtkWidget *scale;
- gimp_prop_opacity_entry_new (config, "sensitivity-b",
- GTK_TABLE (table), 0, row++, "b");
-#endif
+ label = g_object_get_data (object, "label");
+ spin = g_object_get_data (object, "spinbutton");
+ scale = g_object_get_data (object, "scale");
- return vbox;
+ gtk_widget_show (label);
+ gtk_widget_show (spin);
+ gtk_widget_show (scale);
+}
+
+static void
+gimp_foreground_select_hide_scale (GObject *object)
+{
+ GtkWidget *spin;
+ GtkWidget *label;
+ GtkWidget *scale;
+
+ label = g_object_get_data (object, "label");
+ spin = g_object_get_data (object, "spinbutton");
+ scale = g_object_get_data (object, "scale");
+
+ gtk_widget_hide (label);
+ gtk_widget_hide (spin);
+ gtk_widget_hide (scale);
+}
+
+static void
+gimp_foreground_select_notify_engine (GimpToolOptions *tool_options,
+ GParamSpec *pspec,
+ GtkWidget *widget)
+{
+ GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_OPTIONS (tool_options);
+
+ switch (options->engine)
+ {
+ case GIMP_MATTING_ENGINE_MATTING_GLOBAL:
+ gimp_foreground_select_show_scale (options->dynamic_widgets.iterations);
+ gimp_foreground_select_hide_scale (options->dynamic_widgets.levels);
+ gimp_foreground_select_hide_scale (options->dynamic_widgets.active_levels);
+ break;
+
+ case GIMP_MATTING_ENGINE_MATTING_LEVIN:
+ gimp_foreground_select_hide_scale (options->dynamic_widgets.iterations);
+ gimp_foreground_select_show_scale (options->dynamic_widgets.levels);
+ gimp_foreground_select_show_scale (options->dynamic_widgets.active_levels);
+ break;
+ }
+}
+
+gdouble
+gimp_foreground_select_options_get_opacity (GimpForegroundSelectOptions *options)
+{
+ g_return_val_if_fail (GIMP_IS_FOREGROUND_SELECT_OPTIONS (options), 0.0);
+
+ switch (options->draw_mode)
+ {
+ case GIMP_MATTING_DRAW_MODE_FOREGROUND:
+ return 1.0;
+
+ case GIMP_MATTING_DRAW_MODE_BACKGROUND:
+ return 0.0;
+
+ case GIMP_MATTING_DRAW_MODE_UNKNOWN:
+ default:
+ return 0.5;
+ }
}
void
@@ -391,15 +416,19 @@ gimp_foreground_select_options_get_mask_color (GimpForegroundSelectOptions *opti
switch (options->mask_color)
{
case GIMP_RED_CHANNEL:
- gimp_rgba_set (color, 1, 0, 0, 0.5);
+ gimp_rgba_set (color, 1, 0, 0, 0.7);
break;
case GIMP_GREEN_CHANNEL:
- gimp_rgba_set (color, 0, 1, 0, 0.5);
+ gimp_rgba_set (color, 0, 1, 0, 0.7);
break;
case GIMP_BLUE_CHANNEL:
- gimp_rgba_set (color, 0, 0, 1, 0.5);
+ gimp_rgba_set (color, 0, 0, 1, 0.7);
+ break;
+
+ case GIMP_GRAY_CHANNEL:
+ gimp_rgba_set (color, 1, 1, 1, 0.7);
break;
default:
diff --git a/app/tools/gimpforegroundselectoptions.h b/app/tools/gimpforegroundselectoptions.h
index 5423898..1e3f619 100644
--- a/app/tools/gimpforegroundselectoptions.h
+++ b/app/tools/gimpforegroundselectoptions.h
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#ifndef __GIMP_FOREGROUND_SELECT_OPTIONS_H__
#define __GIMP_FOREGROUND_SELECT_OPTIONS_H__
@@ -30,20 +31,35 @@
#define GIMP_FOREGROUND_SELECT_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GIMP_TYPE_FOREGROUND_SELECT_OPTIONS, GimpForegroundSelectOptionsClass))
-typedef struct _GimpForegroundSelectOptions GimpForegroundSelectOptions;
-typedef GimpSelectionOptionsClass GimpForegroundSelectOptionsClass;
+typedef struct _GimpForegroundSelectOptions GimpForegroundSelectOptions;
+typedef struct _GimpForegroundSelectOptionsClass GimpForegroundSelectOptionsClass;
+
+typedef struct _GimpMattingDynamicWidgets GimpMattingDynamicWidgets;
+
+struct _GimpMattingDynamicWidgets
+{
+ GObject *levels;
+ GObject *active_levels;
+ GObject *iterations;
+};
struct _GimpForegroundSelectOptions
{
GimpSelectionOptions parent_instance;
- gboolean contiguous;
- gboolean background;
- gint stroke_width;
- gint smoothness;
- GimpChannelType mask_color;
- gboolean expanded;
- gdouble sensitivity[3];
+ GimpMattingDrawMode draw_mode;
+ gint stroke_width;
+ GimpChannelType mask_color;
+ GimpMattingEngine engine;
+ gint levels;
+ gint active_levels;
+ gint iterations;
+ GimpMattingDynamicWidgets dynamic_widgets;
+};
+
+struct _GimpForegroundSelectOptionsClass
+{
+ GimpSelectionOptionsClass parent_class;
};
@@ -53,6 +69,8 @@ GtkWidget * gimp_foreground_select_options_gui (GimpToolOptions
void gimp_foreground_select_options_get_mask_color (GimpForegroundSelectOptions *options,
GimpRGB *color);
+gdouble gimp_foreground_select_options_get_opacity (GimpForegroundSelectOptions *options);
#endif /* __GIMP_FOREGROUND_SELECT_OPTIONS_H__ */
+
diff --git a/app/tools/gimpforegroundselecttool.c b/app/tools/gimpforegroundselecttool.c
index 2d1792e..01d836f 100644
--- a/app/tools/gimpforegroundselecttool.c
+++ b/app/tools/gimpforegroundselecttool.c
@@ -27,16 +27,18 @@
#include <gdk/gdkkeysyms.h>
#include "libgimpmath/gimpmath.h"
+#include "libgimpcolor/gimpcolor.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
#include "core/gimp.h"
-#include "core/gimpchannel.h"
#include "core/gimpchannel-combine.h"
#include "core/gimpchannel-select.h"
#include "core/gimpdrawable-foreground-extract.h"
#include "core/gimpimage.h"
+#include "core/gimplayer.h"
+#include "core/gimplayermask.h"
#include "core/gimpprogress.h"
#include "core/gimpscanconvert.h"
@@ -105,25 +107,28 @@ static void gimp_foreground_select_tool_motion (GimpTool *tool
static void gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool);
-static void gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
- GimpDisplay *display);
+static void gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
+ GimpDisplay *display);
-static void gimp_foreground_select_tool_set_mask (GimpForegroundSelectTool *fg_select,
- GimpDisplay *display,
- GimpChannel *mask);
-static void gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select,
- GimpDisplay *display);
+static void gimp_foreground_select_tool_set_trimap (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display);
+static void gimp_foreground_select_tool_set_preview (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display);
+static void gimp_foreground_select_tool_drop_masks (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display);
-static void gimp_foreground_select_tool_stroke (GimpChannel *mask,
- FgSelectStroke *stroke);
+static void gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display);
+static void gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display);
-static void gimp_foreground_select_tool_push_stroke (GimpForegroundSelectTool *fg_select,
- GimpDisplay *display,
- GimpForegroundSelectOptions *options);
+static void gimp_foreground_select_options_notify (GimpForegroundSelectOptions *options,
+ GParamSpec *pspec,
+ GimpForegroundSelectTool *fg_select);
-static void gimp_foreground_select_options_notify (GimpForegroundSelectOptions *options,
- GParamSpec *pspec,
- GimpForegroundSelectTool *fg_select);
+static void gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display,
+ GimpForegroundSelectOptions *options);
G_DEFINE_TYPE (GimpForegroundSelectTool, gimp_foreground_select_tool,
@@ -194,10 +199,10 @@ gimp_foreground_select_tool_init (GimpForegroundSelectTool *fg_select)
gimp_tool_control_set_action_value_2 (tool->control,
"tools/tools-foreground-select-brush-size-set");
- fg_select->idle_id = 0;
fg_select->stroke = NULL;
- fg_select->strokes = NULL;
fg_select->mask = NULL;
+ fg_select->trimap = NULL;
+ fg_select->state = MATTING_STATE_FREE_SELECT;
}
static void
@@ -218,18 +223,13 @@ gimp_foreground_select_tool_finalize (GObject *object)
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (object);
if (fg_select->stroke)
- g_warning ("%s: stroke should be NULL at this point", G_STRLOC);
-
- if (fg_select->strokes)
- g_warning ("%s: strokes should be NULL at this point", G_STRLOC);
-
-#if 0
- if (fg_select->state)
- g_warning ("%s: state should be NULL at this point", G_STRLOC);
-#endif
+ g_warning ("%s: stroke should be NULL at this point", G_STRLOC);
if (fg_select->mask)
- g_warning ("%s: mask should be NULL at this point", G_STRLOC);
+ g_warning ("%s: mask should be NULL at this point", G_STRLOC);
+
+ if (fg_select->trimap)
+ g_warning ("%s: mask should be NULL at this point", G_STRLOC);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -249,29 +249,7 @@ gimp_foreground_select_tool_control (GimpTool *tool,
case GIMP_TOOL_ACTION_HALT:
{
- GList *list;
-
- gimp_foreground_select_tool_set_mask (fg_select, display, NULL);
-
- for (list = fg_select->strokes; list; list = list->next)
- {
- FgSelectStroke *stroke = list->data;
-
- g_free (stroke->points);
- g_slice_free (FgSelectStroke, stroke);
- }
-
- g_list_free (fg_select->strokes);
- fg_select->strokes = NULL;
-
-#if 0
- if (fg_select->state)
- {
- gimp_drawable_foreground_extract_siox_done (fg_select->state);
- fg_select->state = NULL;
- }
-#endif
-
+ gimp_foreground_select_tool_drop_masks (fg_select, display);
tool->display = NULL;
}
break;
@@ -293,7 +271,7 @@ gimp_foreground_select_tool_oper_update (GimpTool *tool,
GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
display);
- if (fg_select->mask && display == tool->display)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP && display == tool->display)
{
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
@@ -302,17 +280,17 @@ gimp_foreground_select_tool_oper_update (GimpTool *tool,
fg_select->last_coords = *coords;
gimp_draw_tool_resume (draw_tool);
-
- if (fg_select->strokes)
- status = _("Add more strokes or press Enter to accept the selection");
- else
- status = _("Mark foreground by painting on the object to extract");
+ status = _("Paint trimap, (background, foreground and unknown) or press Enter to preview");
}
- else
+ else if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_SELECT)
status = _("Roughly outline the object to extract");
}
+ else
+ {
+ status = _("Press escape for return to trimap or Enter to apply");
+ }
if (proximity && status)
gimp_tool_replace_status (tool, display, "%s", status);
@@ -325,6 +303,7 @@ gimp_foreground_select_tool_modifier_key (GimpTool *tool,
GdkModifierType state,
GimpDisplay *display)
{
+#if 0
if (key == gimp_get_toggle_behavior_mask ())
{
GimpForegroundSelectOptions *options;
@@ -335,6 +314,7 @@ gimp_foreground_select_tool_modifier_key (GimpTool *tool,
"background", ! options->background,
NULL);
}
+#endif
}
static void
@@ -345,14 +325,8 @@ gimp_foreground_select_tool_cursor_update (GimpTool *tool,
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
- if (fg_select->mask)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
- GimpForegroundSelectOptions *options;
-
- options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
-
- gimp_tool_control_set_toggled (tool->control, options->background);
-
switch (GIMP_SELECTION_TOOL (tool)->function)
{
case SELECTION_MOVE_MASK:
@@ -378,17 +352,14 @@ gimp_foreground_select_tool_key_press (GimpTool *tool,
if (display != tool->display)
return FALSE;
-#if 0
- if (fg_select->state)
-#endif
- if (fg_select->mask) /* dunno if that's the right condition */
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
switch (kevent->keyval)
{
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
- gimp_foreground_select_tool_apply (fg_select, display);
+ gimp_foreground_select_tool_preview (fg_select, display);
return TRUE;
case GDK_KEY_Escape:
@@ -399,6 +370,24 @@ gimp_foreground_select_tool_key_press (GimpTool *tool,
return FALSE;
}
}
+ else if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
+ {
+ switch (kevent->keyval)
+ {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_ISO_Enter:
+ gimp_foreground_select_tool_apply (fg_select, display);
+ return TRUE;
+
+ case GDK_KEY_Escape:
+ gimp_foreground_select_tool_set_trimap (fg_select, display);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
else
{
return GIMP_TOOL_CLASS (parent_class)->key_press (tool,
@@ -418,7 +407,7 @@ gimp_foreground_select_tool_button_press (GimpTool *tool,
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
- if (fg_select->mask)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
GimpVector2 point = gimp_vector2_new (coords->x, coords->y);
@@ -436,12 +425,12 @@ gimp_foreground_select_tool_button_press (GimpTool *tool,
g_array_append_val (fg_select->stroke, point);
- if (! gimp_draw_tool_is_active (draw_tool))
+ if (!gimp_draw_tool_is_active (draw_tool))
gimp_draw_tool_start (draw_tool, display);
gimp_draw_tool_resume (draw_tool);
}
- else
+ else if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
press_type, display);
@@ -458,7 +447,7 @@ gimp_foreground_select_tool_button_release (GimpTool *tool,
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
- if (fg_select->mask)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
GimpForegroundSelectOptions *options;
@@ -468,13 +457,15 @@ gimp_foreground_select_tool_button_release (GimpTool *tool,
gimp_tool_control_halt (tool->control);
- gimp_foreground_select_tool_push_stroke (fg_select, display, options);
+ gimp_foreground_select_tool_stroke_paint (fg_select, display, options);
+
+ gimp_foreground_select_tool_set_trimap (fg_select, display);
gimp_free_select_tool_select (GIMP_FREE_SELECT_TOOL (tool), display);
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
- else
+ else if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
GIMP_TOOL_CLASS (parent_class)->button_release (tool,
coords, time, state,
@@ -492,7 +483,7 @@ gimp_foreground_select_tool_motion (GimpTool *tool,
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
- if (fg_select->mask)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
GimpVector2 *last = &g_array_index (fg_select->stroke,
GimpVector2,
@@ -511,7 +502,7 @@ gimp_foreground_select_tool_motion (GimpTool *tool,
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
- else
+ else if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
GIMP_TOOL_CLASS (parent_class)->motion (tool,
coords, time, state, display);
@@ -550,24 +541,23 @@ gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool)
if (fg_select->stroke)
{
+ GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display);
+
gimp_draw_tool_add_pen (draw_tool,
(const GimpVector2 *) fg_select->stroke->data,
fg_select->stroke->len,
GIMP_CONTEXT (options),
- (options->background ?
- GIMP_ACTIVE_COLOR_BACKGROUND :
- GIMP_ACTIVE_COLOR_FOREGROUND),
- options->stroke_width);
+ GIMP_ACTIVE_COLOR_FOREGROUND,
+ options->stroke_width * shell->scale_y);
}
- if (fg_select->mask)
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
- GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display);
- gint x = fg_select->last_coords.x;
- gint y = fg_select->last_coords.y;
- gdouble radius;
+ gint x = fg_select->last_coords.x;
+ gint y = fg_select->last_coords.y;
+ gdouble radius;
- radius = (options->stroke_width / shell->scale_y) / 2;
+ radius = options->stroke_width / 2;
/* warn if the user is drawing outside of the working area */
if (FALSE)
@@ -592,7 +582,7 @@ gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool)
2 * radius, 2 * radius,
0.0, 2.0 * G_PI);
}
- else
+ else if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
}
@@ -602,110 +592,111 @@ static void
gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
GimpDisplay *display)
{
- GimpForegroundSelectTool *fg_select;
- GimpForegroundSelectOptions *options;
- GimpImage *image = gimp_display_get_image (display);
- GimpDrawable *drawable;
- GimpScanConvert *scan_convert;
- GimpChannel *mask;
- const GimpVector2 *points;
- gint n_points;
+ GimpForegroundSelectTool *fg_select;
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDrawable *drawable;
+ GimpScanConvert *scan_convert;
+ const GimpVector2 *points;
+ gint n_points;
drawable = gimp_image_get_active_drawable (image);
fg_select = GIMP_FOREGROUND_SELECT_TOOL (free_sel);
- options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (free_sel);
-
- if (fg_select->idle_id)
- {
- g_source_remove (fg_select->idle_id);
- fg_select->idle_id = 0;
- }
if (! drawable)
return;
- scan_convert = gimp_scan_convert_new ();
-
- gimp_free_select_tool_get_points (free_sel,
- &points,
- &n_points);
-
- gimp_scan_convert_add_polyline (scan_convert,
- n_points,
- points,
- TRUE);
-
- mask = gimp_channel_new (image,
- gimp_image_get_width (image),
- gimp_image_get_height (image),
- "foreground-extraction", NULL);
-
- gimp_scan_convert_render_value (scan_convert,
- gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)),
- 0, 0, 0.5);
- gimp_scan_convert_free (scan_convert);
-
- if (fg_select->strokes)
+ if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
- GList *list;
+ scan_convert = gimp_scan_convert_new ();
- gimp_set_busy (image->gimp);
+ gimp_free_select_tool_get_points (free_sel,
+ &points,
+ &n_points);
- /* apply foreground and background markers */
- for (list = fg_select->strokes; list; list = list->next)
- gimp_foreground_select_tool_stroke (mask, list->data);
+ gimp_scan_convert_add_polyline (scan_convert,
+ n_points,
+ points,
+ TRUE);
-#if 0
- if (fg_select->state)
- gimp_drawable_foreground_extract_siox (GIMP_DRAWABLE (mask),
- fg_select->state,
- fg_select->refinement,
- options->smoothness,
- options->sensitivity,
- ! options->contiguous,
- GIMP_PROGRESS (fg_select));
-#endif
+ fg_select->trimap = gimp_channel_new (image,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ "foreground-extraction",NULL);
- fg_select->refinement = SIOX_REFINEMENT_NO_CHANGE;
+ gimp_scan_convert_render_value (scan_convert,
+ gimp_drawable_get_buffer (GIMP_DRAWABLE (fg_select->trimap)),
+ 0, 0, 1.0);
+ gimp_scan_convert_free (scan_convert);
- gimp_unset_busy (image->gimp);
+ gimp_foreground_select_tool_set_trimap (fg_select, display);
}
- else
- {
- gint x1, y1;
- gint x2, y2;
+}
- g_object_set (options, "background", FALSE, NULL);
+static void
+gimp_foreground_select_tool_set_trimap (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display)
+{
+ GimpTool *tool = GIMP_TOOL (fg_select);
+ GimpForegroundSelectOptions *options;
+ GimpRGB color;
- gimp_foreground_select_tool_get_area (mask, &x1, &y1, &x2, &y2);
+ g_return_if_fail (fg_select->trimap != NULL);
-#if 0
- if (fg_select->state)
- g_warning ("state should be NULL here");
+ options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
- fg_select->state =
- gimp_drawable_foreground_extract_siox_init (drawable,
- x1, y1, x2 - x1, y2 - y1);
-#endif
- }
+ gimp_foreground_select_options_get_mask_color (options, &color);
+ gimp_display_shell_set_mask (gimp_display_get_shell (display),
+ GIMP_DRAWABLE (fg_select->trimap), &color);
+
+ gimp_tool_control_set_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_PAINTBRUSH);
+ gimp_tool_control_set_toggle_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_PAINTBRUSH);
- gimp_foreground_select_tool_set_mask (fg_select, display, mask);
+ gimp_tool_control_set_toggled (tool->control, FALSE);
- g_object_unref (mask);
+ fg_select->state = MATTING_STATE_PAINT_TRIMAP;
}
static void
-gimp_foreground_select_tool_set_mask (GimpForegroundSelectTool *fg_select,
- GimpDisplay *display,
- GimpChannel *mask)
+gimp_foreground_select_tool_set_preview (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display)
{
+
GimpTool *tool = GIMP_TOOL (fg_select);
GimpForegroundSelectOptions *options;
+ GimpRGB color;
+
+ g_return_if_fail (fg_select->mask != NULL);
options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
- if (fg_select->mask == mask)
- return;
+ gimp_foreground_select_options_get_mask_color (options, &color);
+ gimp_rgb_set_alpha (&color, 1.0);
+ gimp_display_shell_set_mask (gimp_display_get_shell (display),
+ GIMP_DRAWABLE (fg_select->mask), &color);
+
+ gimp_tool_control_set_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_PAINTBRUSH);
+ gimp_tool_control_set_toggle_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_PAINTBRUSH);
+
+ gimp_tool_control_set_toggled (tool->control, FALSE);
+
+ fg_select->state = MATTING_STATE_PREVIEW_MASK;
+}
+
+static void
+gimp_foreground_select_tool_drop_masks (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display)
+{
+ GimpTool *tool = GIMP_TOOL (fg_select);
+
+ if (fg_select->trimap)
+ {
+ g_object_unref (fg_select->trimap);
+ fg_select->trimap = NULL;
+ }
if (fg_select->mask)
{
@@ -713,59 +704,136 @@ gimp_foreground_select_tool_set_mask (GimpForegroundSelectTool *fg_select,
fg_select->mask = NULL;
}
- if (mask)
- {
- GimpRGB color;
-
- fg_select->mask = g_object_ref (mask);
-
- gimp_foreground_select_options_get_mask_color (options, &color);
- gimp_display_shell_set_mask (gimp_display_get_shell (display),
- GIMP_DRAWABLE (mask), &color);
- }
- else
+ if (GIMP_IS_DISPLAY (display))
{
gimp_display_shell_set_mask (gimp_display_get_shell (display),
NULL, NULL);
}
- if (mask)
+ gimp_tool_control_set_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_FREE_SELECT);
+ gimp_tool_control_set_toggle_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_FREE_SELECT);
+
+ gimp_tool_control_set_toggled (tool->control, FALSE);
+ fg_select->state = MATTING_STATE_FREE_SELECT;
+}
+
+static void
+gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display)
+{
+ GimpTool *tool = GIMP_TOOL (fg_select);
+ GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GeglBuffer *trimap_buffer;
+ GeglBuffer *drawable_buffer;
+ GeglNode *gegl;
+ GeglNode *matting_node;
+ GeglNode *input_image;
+ GeglNode *input_trimap;
+ GeglNode *output_mask;
+ GeglBuffer *buffer;
+ GimpProgress *progress;
+ GeglProcessor *processor;
+ gdouble value;
+
+ if (fg_select->mask)
{
- gimp_tool_control_set_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_PAINTBRUSH);
- gimp_tool_control_set_toggle_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_ERASER);
+ g_object_unref (fg_select->mask);
+ fg_select->mask = NULL;
+ }
- gimp_tool_control_set_toggled (tool->control, options->background);
+ progress = gimp_progress_start (GIMP_PROGRESS (fg_select),
+ _("Computing alpha of unknown pixels"),
+ FALSE);
+
+ trimap_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (fg_select->trimap));
+ drawable_buffer = gimp_drawable_get_buffer (drawable);
+
+ gegl = gegl_node_new ();
+
+ input_trimap = gegl_node_new_child (gegl,
+ "operation", "gegl:buffer-source",
+ "buffer", trimap_buffer,
+ NULL);
+ input_image = gegl_node_new_child (gegl,
+ "operation", "gegl:buffer-source",
+ "buffer", drawable_buffer,
+ NULL);
+ output_mask = gegl_node_new_child (gegl,
+ "operation", "gegl:buffer-sink",
+ "buffer", &buffer,
+ "format", NULL,
+ NULL);
+
+ if (options->engine == GIMP_MATTING_ENGINE_MATTING_GLOBAL)
+ {
+ matting_node = gegl_node_new_child (gegl,
+ "operation", "gegl:matting-global",
+ "iterations", options->iterations,
+ NULL);
}
else
{
- gimp_tool_control_set_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_FREE_SELECT);
- gimp_tool_control_set_toggle_tool_cursor (tool->control,
- GIMP_TOOL_CURSOR_FREE_SELECT);
+ matting_node = gegl_node_new_child (gegl,
+ "operation", "gegl:matting-levin",
+ "levels", options->levels,
+ "active_levels", options->active_levels,
+ NULL);
+ }
- gimp_tool_control_set_toggled (tool->control, FALSE);
+ gegl_node_connect_to (input_image, "output",
+ matting_node, "input");
+ gegl_node_connect_to (input_trimap, "output",
+ matting_node, "aux");
+ gegl_node_connect_to (matting_node, "output",
+ output_mask, "input");
+
+ processor = gegl_node_new_processor (output_mask, NULL);
+
+ while (gegl_processor_work (processor, &value))
+ {
+ if (progress)
+ gimp_progress_set_value (progress, value);
}
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ g_object_unref (processor);
+
+ fg_select->mask = gimp_channel_new_from_buffer (buffer, image,
+ "preview-mask", NULL);
+
+ gimp_foreground_select_tool_set_preview (fg_select, display);
+
+ g_object_unref (gegl);
+
+ if (buffer)
+ g_object_unref (buffer);
}
static void
gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select,
GimpDisplay *display)
{
- GimpTool *tool = GIMP_TOOL (fg_select);
- GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
- GimpImage *image = gimp_display_get_image (display);
+ GimpTool *tool = GIMP_TOOL (fg_select);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpLayer *layer = gimp_image_get_active_layer (image);
+ GeglBuffer *buffer;
+ GimpLayerMask *layer_mask;
+ GimpRGB color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
g_return_if_fail (fg_select->mask != NULL);
- gimp_channel_select_channel (gimp_image_get_mask (image),
- C_("command", "Foreground Select"),
- fg_select->mask, 0, 0,
- options->operation,
- options->feather,
- options->feather_radius,
- options->feather_radius);
+ buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (fg_select->mask));
+
+ layer_mask = gimp_layer_mask_new_from_buffer (buffer, image,
+ "mask", &color);
+
+ gimp_layer_add_mask (layer, layer_mask, TRUE, NULL);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
@@ -773,16 +841,22 @@ gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select,
}
static void
-gimp_foreground_select_tool_stroke (GimpChannel *mask,
- FgSelectStroke *stroke)
+gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTool *fg_select,
+ GimpDisplay *display,
+ GimpForegroundSelectOptions *options)
{
- GimpScanConvert *scan_convert = gimp_scan_convert_new ();
+ GimpScanConvert *scan_convert;
+ gint width;
+
+ g_return_if_fail (fg_select->stroke != NULL);
+
+ scan_convert = gimp_scan_convert_new ();
- if (stroke->num_points == 1)
+ if (fg_select->stroke->len == 1)
{
GimpVector2 points[2];
- points[0] = points[1] = stroke->points[0];
+ points[0] = points[1] = ((GimpVector2 *) fg_select->stroke->data)[0];
points[1].x += 0.01;
points[1].y += 0.01;
@@ -792,111 +866,50 @@ gimp_foreground_select_tool_stroke (GimpChannel *mask,
else
{
gimp_scan_convert_add_polyline (scan_convert,
- stroke->num_points, stroke->points,
+ fg_select->stroke->len,
+ (GimpVector2 *) fg_select->stroke->data,
FALSE);
}
+ width = ROUND ((gdouble) options->stroke_width);
+
gimp_scan_convert_stroke (scan_convert,
- stroke->width,
+ width,
GIMP_JOIN_ROUND, GIMP_CAP_ROUND, 10.0,
0.0, NULL);
- gimp_scan_convert_compose_value (scan_convert,
- gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)),
- 0, 0, stroke->background ? 0.0 : 1.0);
- gimp_scan_convert_free (scan_convert);
-}
-static void
-gimp_foreground_select_tool_push_stroke (GimpForegroundSelectTool *fg_select,
- GimpDisplay *display,
- GimpForegroundSelectOptions *options)
-{
- GimpDisplayShell *shell = gimp_display_get_shell (display);
- FgSelectStroke *stroke;
-
- g_return_if_fail (fg_select->stroke != NULL);
-
- stroke = g_slice_new (FgSelectStroke);
+ gimp_scan_convert_compose_value (scan_convert,
+ gimp_drawable_get_buffer (GIMP_DRAWABLE (fg_select->trimap)),
+ 0, 0,
+ gimp_foreground_select_options_get_opacity (options));
- stroke->background = options->background;
- stroke->width = ROUND ((gdouble) options->stroke_width / shell->scale_y);
- stroke->num_points = fg_select->stroke->len;
- stroke->points = (GimpVector2 *) g_array_free (fg_select->stroke, FALSE);
+ gimp_scan_convert_free (scan_convert);
+ g_array_free (fg_select->stroke, TRUE);
fg_select->stroke = NULL;
- fg_select->strokes = g_list_append (fg_select->strokes, stroke);
-
- fg_select->refinement |= (stroke->background ?
- SIOX_REFINEMENT_ADD_BACKGROUND :
- SIOX_REFINEMENT_ADD_FOREGROUND);
-}
-
-static gboolean
-gimp_foreground_select_tool_idle_select (GimpForegroundSelectTool *fg_select)
-{
- GimpTool *tool = GIMP_TOOL (fg_select);
-
- fg_select->idle_id = 0;
-
- if (tool->display)
- gimp_free_select_tool_select (GIMP_FREE_SELECT_TOOL (tool), tool->display);
-
- return FALSE;
}
-/* To compress close notify signals, the process is delayed by */
-#define MINIMUM_DELAY 300
-
static void
gimp_foreground_select_options_notify (GimpForegroundSelectOptions *options,
GParamSpec *pspec,
GimpForegroundSelectTool *fg_select)
{
- SioxRefinementType refinement = 0;
-
- if (! fg_select->mask)
- return;
-
-#if 0
- if (strcmp (pspec->name, "smoothness") == 0)
- {
- refinement = SIOX_REFINEMENT_CHANGE_SMOOTHNESS;
- }
- else if (strcmp (pspec->name, "contiguous") == 0)
- {
- refinement = SIOX_REFINEMENT_CHANGE_MULTIBLOB;
- }
- else if (g_str_has_prefix (pspec->name, "sensitivity"))
- {
- refinement = SIOX_REFINEMENT_CHANGE_SENSITIVITY;
- }
-#endif
-
- if (refinement && fg_select->strokes)
- {
- fg_select->refinement |= refinement;
-
- if (fg_select->idle_id)
- g_source_remove (fg_select->idle_id);
-
- fg_select->idle_id =
- g_timeout_add_full (G_PRIORITY_LOW, MINIMUM_DELAY,
- (GSourceFunc) gimp_foreground_select_tool_idle_select,
- fg_select, NULL);
- }
-
if (g_str_has_prefix (pspec->name, "mask-color"))
{
GimpTool *tool = GIMP_TOOL (fg_select);
- if (tool->display && fg_select->mask)
+ if (tool->display)
{
- GimpRGB color;
+ if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
+ {
+ gimp_foreground_select_tool_set_trimap (fg_select, tool->display);
+ }
- gimp_foreground_select_options_get_mask_color (options, &color);
- gimp_display_shell_set_mask (gimp_display_get_shell (tool->display),
- GIMP_DRAWABLE (fg_select->mask), &color);
+ if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
+ {
+ gimp_foreground_select_tool_set_preview (fg_select, tool->display);
+ }
}
}
}
diff --git a/app/tools/gimpforegroundselecttool.h b/app/tools/gimpforegroundselecttool.h
index 2903724..f2e2982 100644
--- a/app/tools/gimpforegroundselecttool.h
+++ b/app/tools/gimpforegroundselecttool.h
@@ -22,13 +22,12 @@
#include "gimpfreeselecttool.h"
-typedef enum /*< pdb-skip, skip >*/
+typedef enum
{
- SIOX_REFINEMENT_NO_CHANGE = 0,
- SIOX_REFINEMENT_ADD_FOREGROUND = (1 << 0),
- SIOX_REFINEMENT_ADD_BACKGROUND = (1 << 1),
- SIOX_REFINEMENT_RECALCULATE = 0xFF
-} SioxRefinementType;
+ MATTING_STATE_FREE_SELECT = 0,
+ MATTING_STATE_PAINT_TRIMAP,
+ MATTING_STATE_PREVIEW_MASK,
+} MattingState;
#define GIMP_TYPE_FOREGROUND_SELECT_TOOL (gimp_foreground_select_tool_get_type ())
@@ -49,14 +48,10 @@ struct _GimpForegroundSelectTool
GimpFreeSelectTool parent_instance;
GimpCoords last_coords;
- guint idle_id;
GArray *stroke;
- GList *strokes;
+ GimpChannel *trimap;
GimpChannel *mask;
-#if 0
- SioxState *state;
-#endif
- SioxRefinementType refinement;
+ MattingState state;
};
struct _GimpForegroundSelectToolClass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]