Commit e2628b9b authored by Michael Natterer's avatar Michael Natterer 😴
Browse files

app: revive gimpdrawable-foreground-extract

Move the extraction graph from the foreground select tool there.
Enable the PDB wrapper again, using default values for now.
Some sytle cleanup in the foreground select tool.
parent bcdf1a31
......@@ -324,6 +324,35 @@ gimp_layer_mode_effects_get_type (void)
return type;
}
GType
gimp_matting_engine_get_type (void)
{
static const GEnumValue values[] =
{
{ GIMP_MATTING_ENGINE_GLOBAL, "GIMP_MATTING_ENGINE_GLOBAL", "global" },
{ GIMP_MATTING_ENGINE_LEVIN, "GIMP_MATTING_ENGINE_LEVIN", "levin" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
{ GIMP_MATTING_ENGINE_GLOBAL, NC_("matting-engine", "Matting Global"), NULL },
{ GIMP_MATTING_ENGINE_LEVIN, NC_("matting-engine", "Matting Levin"), NULL },
{ 0, NULL, NULL }
};
static GType type = 0;
if (G_UNLIKELY (! type))
{
type = g_enum_register_static ("GimpMattingEngine", values);
gimp_type_set_translation_context (type, "matting-engine");
gimp_enum_set_value_descriptions (type, descs);
}
return type;
}
GType
gimp_alignment_type_get_type (void)
{
......
......@@ -168,6 +168,17 @@ typedef enum
} GimpLayerModeEffects;
#define GIMP_TYPE_MATTING_ENGINE (gimp_matting_engine_get_type ())
GType gimp_matting_engine_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_MATTING_ENGINE_GLOBAL, /*< desc="Matting Global" >*/
GIMP_MATTING_ENGINE_LEVIN, /*< desc="Matting Levin" >*/
} GimpMattingEngine;
#define GIMP_TYPE_ALIGNMENT_TYPE (gimp_alignment_type_get_type ())
GType gimp_alignment_type_get_type (void) G_GNUC_CONST;
......
......@@ -15,19 +15,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if 0
#include "config.h"
#include <gio/gio.h>
#include <gegl.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "libgimpbase/gimpbase.h"
#include "core-types.h"
#include "base/siox.h"
#include "base/tile-manager.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimpchannel.h"
......@@ -41,137 +38,88 @@
/* public functions */
void
gimp_drawable_foreground_extract (GimpDrawable *drawable,
GimpForegroundExtractMode mode,
GimpDrawable *mask,
GimpProgress *progress)
GeglBuffer *
gimp_drawable_foreground_extract (GimpDrawable *drawable,
GimpMattingEngine engine,
gint global_iterations,
gint levin_levels,
gint levin_active_levels,
GeglBuffer *trimap,
GimpProgress *progress)
{
SioxState *state;
const gdouble sensitivity[3] = { SIOX_DEFAULT_SENSITIVITY_L,
SIOX_DEFAULT_SENSITIVITY_A,
SIOX_DEFAULT_SENSITIVITY_B };
g_return_if_fail (GIMP_IS_DRAWABLE (mask));
g_return_if_fail (mode == GIMP_FOREGROUND_EXTRACT_SIOX);
state =
gimp_drawable_foreground_extract_siox_init (drawable,
0, 0,
gimp_item_get_width (GIMP_ITEM (mask)),
gimp_item_get_height (GIMP_ITEM (mask)));
if (state)
{
gimp_drawable_foreground_extract_siox (mask, state,
SIOX_REFINEMENT_RECALCULATE,
SIOX_DEFAULT_SMOOTHNESS,
sensitivity,
FALSE,
progress);
gimp_drawable_foreground_extract_siox_done (state);
}
}
SioxState *
gimp_drawable_foreground_extract_siox_init (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height)
{
GeglBuffer *buffer;
const guchar *colormap = NULL;
gboolean intersect;
gint offset_x;
gint offset_y;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
if (gimp_drawable_is_indexed (drawable))
colormap = gimp_drawable_get_colormap (drawable);
gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
intersect = gimp_rectangle_intersect (offset_x, offset_y,
gimp_item_get_width (GIMP_ITEM (drawable)),
gimp_item_get_height (GIMP_ITEM (drawable)),
x, y, width, height,
&x, &y, &width, &height);
/* FIXME:
* Clear the mask outside the rectangle that we are working on?
*/
if (! intersect)
return NULL;
buffer = gimp_drawable_get_buffer (drawable);
return siox_init (gimp_gegl_buffer_get_tiles (buffer), colormap,
offset_x, offset_y,
x, y, width, height);
}
void
gimp_drawable_foreground_extract_siox (GimpDrawable *mask,
SioxState *state,
SioxRefinementType refinement,
gint smoothness,
const gdouble sensitivity[3],
gboolean multiblob,
GimpProgress *progress)
{
GeglBuffer *buffer;
gint x1, y1;
gint x2, y2;
g_return_if_fail (GIMP_IS_DRAWABLE (mask));
g_return_if_fail (babl_format_get_bytes_per_pixel (gimp_drawable_get_format (mask)) == 1);
g_return_if_fail (state != NULL);
GeglBuffer *drawable_buffer;
GeglNode *gegl;
GeglNode *input_node;
GeglNode *trimap_node;
GeglNode *matting_node;
GeglNode *output_node;
GeglBuffer *buffer;
GeglProcessor *processor;
gdouble value;
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (GEGL_IS_BUFFER (trimap));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
if (progress)
gimp_progress_start (progress, _("Foreground Extraction"), FALSE);
if (GIMP_IS_CHANNEL (mask))
progress = gimp_progress_start (progress,
_("Computing alpha of unknown pixels"),
FALSE);
drawable_buffer = gimp_drawable_get_buffer (drawable);
gegl = gegl_node_new ();
trimap_node = gegl_node_new_child (gegl,
"operation", "gegl:buffer-source",
"buffer", trimap,
NULL);
input_node = gegl_node_new_child (gegl,
"operation", "gegl:buffer-source",
"buffer", drawable_buffer,
NULL);
output_node = gegl_node_new_child (gegl,
"operation", "gegl:buffer-sink",
"buffer", &buffer,
"format", NULL,
NULL);
if (engine == GIMP_MATTING_ENGINE_GLOBAL)
{
gimp_channel_bounds (GIMP_CHANNEL (mask), &x1, &y1, &x2, &y2);
matting_node = gegl_node_new_child (gegl,
"operation", "gegl:matting-global",
"iterations", global_iterations,
NULL);
}
else
{
x1 = 0;
y1 = 0;
x2 = gimp_item_get_width (GIMP_ITEM (mask));
y2 = gimp_item_get_height (GIMP_ITEM (mask));
matting_node = gegl_node_new_child (gegl,
"operation", "gegl:matting-levin",
"levels", levin_levels,
"active_levels", levin_active_levels,
NULL);
}
buffer = gimp_drawable_get_buffer (mask);
gegl_node_connect_to (input_node, "output",
matting_node, "input");
gegl_node_connect_to (trimap_node, "output",
matting_node, "aux");
gegl_node_connect_to (matting_node, "output",
output_node, "input");
siox_foreground_extract (state, refinement,
gimp_gegl_buffer_get_tiles (buffer),
x1, y1, x2, y2,
smoothness, sensitivity, multiblob,
(SioxProgressFunc) gimp_progress_set_value,
progress);
processor = gegl_node_new_processor (output_node, NULL);
while (gegl_processor_work (processor, &value))
{
if (progress)
gimp_progress_set_value (progress, value);
}
if (progress)
gimp_progress_end (progress);
gimp_drawable_update (mask, x1, y1, x2, y2);
}
g_object_unref (processor);
void
gimp_drawable_foreground_extract_siox_done (SioxState *state)
{
g_return_if_fail (state != NULL);
g_object_unref (gegl);
siox_done (state);
return buffer;
}
#endif
......@@ -15,36 +15,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if 0
#ifndef __GIMP_DRAWABLE_FOREGROUND_EXTRACT_H__
#define __GIMP_DRAWABLE_FOREGROUND_EXTRACT_H__
/* general API (as seen from the PDB) */
void gimp_drawable_foreground_extract (GimpDrawable *drawable,
GimpForegroundExtractMode mode,
GimpDrawable *mask,
GimpProgress *progress);
/* SIOX specific API */
SioxState * gimp_drawable_foreground_extract_siox_init (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height);
void gimp_drawable_foreground_extract_siox (GimpDrawable *mask,
SioxState *state,
SioxRefinementType refinemane,
gint smoothness,
const gdouble sensitivity[3],
gboolean multiblob,
GimpProgress *progress);
void gimp_drawable_foreground_extract_siox_done (SioxState *state);
GeglBuffer * gimp_drawable_foreground_extract (GimpDrawable *drawable,
GimpMattingEngine engine,
gint global_iterations,
gint levin_levels,
gint levin_active_levels,
GeglBuffer *trimap,
GimpProgress *progress);
#endif /* __GIMP_DRAWABLE_FOREGROUND_EXTRACT_H__ */
#endif
......@@ -29,6 +29,7 @@
#include "config/gimpcoreconfig.h"
#include "core/gimp.h"
#include "core/gimpchannel-select.h"
#include "core/gimpdrawable-foreground-extract.h"
#include "core/gimpdrawable-offset.h"
#include "core/gimpdrawable-preview.h"
......@@ -45,6 +46,7 @@
#include "gimppdb.h"
#include "gimppdb-utils.h"
#include "gimppdbcontext.h"
#include "gimpprocedure.h"
#include "internal-procs.h"
......@@ -938,13 +940,35 @@ drawable_foreground_extract_invoker (GimpProcedure *procedure,
if (success)
{
/*
if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, 0, error))
gimp_drawable_foreground_extract (drawable, mode, mask, progress);
if (mode == GIMP_FOREGROUND_EXTRACT_MATTING &&
gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, 0, error))
{
GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
GeglBuffer *buffer;
buffer = gimp_drawable_foreground_extract (drawable,
GIMP_MATTING_ENGINE_GLOBAL,
2,
2,
2,
gimp_drawable_get_buffer (mask),
progress);
gimp_channel_select_buffer (gimp_image_get_mask (image),
C_("command", "Foreground Select"),
buffer,
0, /* x offset */
0, /* y offset */
GIMP_CHANNEL_OP_REPLACE,
pdb_context->feather,
pdb_context->feather_radius_x,
pdb_context->feather_radius_y);
g_object_unref (buffer);
}
else
success = FALSE;
*/
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
......
......@@ -745,8 +745,10 @@ gimp_foreground_select_tool_options_notify (GimpTool *tool,
GimpToolOptions *options,
const GParamSpec *pspec)
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
GimpForegroundSelectOptions *fg_options = GIMP_FOREGROUND_SELECT_OPTIONS (options);
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
GimpForegroundSelectOptions *fg_options;
fg_options = GIMP_FOREGROUND_SELECT_OPTIONS (options);
if (! tool->display)
return;
......@@ -754,27 +756,37 @@ gimp_foreground_select_tool_options_notify (GimpTool *tool,
if (! strcmp (pspec->name, "mask-color"))
{
if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
gimp_foreground_select_tool_set_trimap (fg_select);
{
gimp_foreground_select_tool_set_trimap (fg_select);
}
else if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_set_preview (fg_select);
{
gimp_foreground_select_tool_set_preview (fg_select);
}
}
else if (! strcmp (pspec->name, "engine"))
{
if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_preview (fg_select);
{
gimp_foreground_select_tool_preview (fg_select);
}
}
else if (! strcmp (pspec->name, "iterations"))
{
if (fg_options->engine == GIMP_MATTING_ENGINE_GLOBAL &&
fg_select->state == MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_preview (fg_select);
{
gimp_foreground_select_tool_preview (fg_select);
}
}
else if (! strcmp (pspec->name, "levels") ||
! strcmp (pspec->name, "active-levels"))
{
if (fg_options->engine == GIMP_MATTING_ENGINE_LEVIN &&
fg_select->state == MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_preview (fg_select);
{
gimp_foreground_select_tool_preview (fg_select);
}
}
}
......@@ -802,12 +814,11 @@ gimp_foreground_select_tool_get_area (GeglBuffer *mask,
static void
gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool)
{
GimpTool *tool = GIMP_TOOL (draw_tool);
GimpForegroundSelectTool *fg_select;
GimpTool *tool = GIMP_TOOL (draw_tool);
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
GimpForegroundSelectOptions *options;
fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
......@@ -861,16 +872,13 @@ static void
gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
GimpDisplay *display)
{
GimpForegroundSelectTool *fg_select;
GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable;
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (free_sel);
GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpScanConvert *scan_convert;
const GimpVector2 *points;
gint n_points;
drawable = gimp_image_get_active_drawable (image);
fg_select = GIMP_FOREGROUND_SELECT_TOOL (free_sel);
if (! drawable)
return;
......@@ -887,10 +895,11 @@ gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
points,
TRUE);
fg_select->trimap = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
gimp_image_get_width (image),
gimp_image_get_height (image)),
gimp_image_get_mask_format (image));
fg_select->trimap =
gegl_buffer_new (GEGL_RECTANGLE (0, 0,
gimp_image_get_width (image),
gimp_image_get_height (image)),
gimp_image_get_mask_format (image));
gimp_scan_convert_render_value (scan_convert, fg_select->trimap,
0, 0, 0.5);
......@@ -1041,20 +1050,11 @@ static void
gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select)
{
GimpTool *tool = GIMP_TOOL (fg_select);
GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
GimpForegroundSelectOptions *options;
GimpImage *image = gimp_display_get_image (tool->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;
options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
if (fg_select->mask)
{
......@@ -1062,70 +1062,15 @@ gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select)
fg_select->mask = NULL;
}
progress = gimp_progress_start (GIMP_PROGRESS (fg_select),
_("Computing alpha of unknown pixels"),
FALSE);
trimap_buffer = 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_GLOBAL)
{
matting_node = gegl_node_new_child (gegl,
"operation", "gegl:matting-global",
"iterations", options->iterations,
NULL);
}
else
{
matting_node = gegl_node_new_child (gegl,
"operation", "gegl:matting-levin",
"levels", options->levels,
"active_levels", options->active_levels,
NULL);
}
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 = buffer;
fg_select->mask = gimp_drawable_foreground_extract (drawable,
options->engine,
options->iterations,
options->levels,
options->active_levels,
fg_select->trimap,
GIMP_PROGRESS (fg_select));
gimp_foreground_select_tool_set_preview (fg_select);
g_object_unref (gegl);
}
static void
......
......@@ -323,35 +323,6 @@ gimp_matting_draw_mode_get_type (void)
return type;
}
GType
gimp_matting_engine_get_type (void)
{
static const GEnumValue values[] =
{
{ GIMP_MATTING_ENGINE_GLOBAL, "GIMP_MATTING_ENGINE_GLOBAL", "global" },
{ GIMP_MATTING_ENGINE_LEVIN, "GIMP_MATTING_ENGINE_LEVIN", "levin" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
{ GIMP_MATTING_ENGINE_GLOBAL, NC_("matting-engine", "Matting Global"), NULL },
{ GIMP_MATTING_ENGINE_LEVIN, NC_("matting-engine", "Matting Levin"), NULL },
{ 0, NULL, NULL }