[gimp/soc-2011-seamless-clone] Add outline finding code for the tool, including outline preview
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2011-seamless-clone] Add outline finding code for the tool, including outline preview
- Date: Mon, 18 Jul 2011 15:18:08 +0000 (UTC)
commit e3908956d5d4759ea445191f97d658915a8ed281
Author: Barak Itkin <lightningismyname gmail com>
Date: Mon Jul 18 18:15:41 2011 +0300
Add outline finding code for the tool, including outline preview
app/gegl/Makefile.am | 2 +
app/gegl/gimp-gegl-types.h | 1 +
app/gegl/gimp-gegl.c | 2 +
app/gegl/gimpoperationfindoutline.c | 430 +++++++++++++++++++++++++++++++++++
app/gegl/gimpoperationfindoutline.h | 68 ++++++
app/tools/gimpseamlessclonetool.c | 80 ++++++-
app/tools/gimpseamlessclonetool.h | 2 +
7 files changed, 580 insertions(+), 5 deletions(-)
---
diff --git a/app/gegl/Makefile.am b/app/gegl/Makefile.am
index addc33f..bcd5143 100644
--- a/app/gegl/Makefile.am
+++ b/app/gegl/Makefile.am
@@ -65,6 +65,8 @@ libappgegl_a_sources = \
gimpoperationcurves.h \
gimpoperationdesaturate.c \
gimpoperationdesaturate.h \
+ gimpoperationfindoutline.c \
+ gimpoperationfindoutline.h \
gimpoperationhuesaturation.c \
gimpoperationhuesaturation.h \
gimpoperationlevels.c \
diff --git a/app/gegl/gimp-gegl-types.h b/app/gegl/gimp-gegl-types.h
index af17404..413d341 100644
--- a/app/gegl/gimp-gegl-types.h
+++ b/app/gegl/gimp-gegl-types.h
@@ -37,6 +37,7 @@ typedef struct _GimpOperationCageCoefCalc GimpOperationCageCoefCalc;
typedef struct _GimpOperationCageTransform GimpOperationCageTransform;
typedef struct _GimpOperationCurves GimpOperationCurves;
typedef struct _GimpOperationDesaturate GimpOperationDesaturate;
+typedef struct _GimpOperationFindOutline GimpOperationFindOutline;
typedef struct _GimpOperationHueSaturation GimpOperationHueSaturation;
typedef struct _GimpOperationLevels GimpOperationLevels;
typedef struct _GimpOperationPosterize GimpOperationPosterize;
diff --git a/app/gegl/gimp-gegl.c b/app/gegl/gimp-gegl.c
index e5f8a51..c07f380 100644
--- a/app/gegl/gimp-gegl.c
+++ b/app/gegl/gimp-gegl.c
@@ -37,6 +37,7 @@
#include "gimpoperationcolorize.h"
#include "gimpoperationcurves.h"
#include "gimpoperationdesaturate.h"
+#include "gimpoperationfindoutline.h"
#include "gimpoperationhuesaturation.h"
#include "gimpoperationlevels.h"
#include "gimpoperationposterize.h"
@@ -103,6 +104,7 @@ gimp_gegl_init (Gimp *gimp)
g_type_class_ref (GIMP_TYPE_OPERATION_COLORIZE);
g_type_class_ref (GIMP_TYPE_OPERATION_CURVES);
g_type_class_ref (GIMP_TYPE_OPERATION_DESATURATE);
+ g_type_class_ref (GIMP_TYPE_OPERATION_FIND_OUTLINE);
g_type_class_ref (GIMP_TYPE_OPERATION_HUE_SATURATION);
g_type_class_ref (GIMP_TYPE_OPERATION_LEVELS);
g_type_class_ref (GIMP_TYPE_OPERATION_POSTERIZE);
diff --git a/app/gegl/gimpoperationfindoutline.c b/app/gegl/gimpoperationfindoutline.c
new file mode 100644
index 0000000..b54bc72
--- /dev/null
+++ b/app/gegl/gimpoperationfindoutline.c
@@ -0,0 +1,430 @@
+/* GIMP - The GNU Image Manipulation Program
+ *
+ * gimpoperationfindoutline.c
+ * Copyright (C) 2011 Barak Itkin <lightningismyname gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <gegl.h>
+
+#include "gimp-gegl-types.h"
+
+#include "gimpoperationfindoutline.h"
+
+#include <stdio.h> /* TODO: get rid of this debugging way! */
+
+enum
+{
+ PROP0,
+ PROP_POINTS,
+ PROP_THRESHOLD,
+ PROP_X,
+ PROP_Y,
+ PROP_WIDTH,
+ PROP_HEIGHT
+};
+
+static void
+gimp_operation_find_outline_init (GimpOperationFindOutline *self);
+
+static void
+gimp_operation_find_outline_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void
+gimp_operation_find_outline_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+
+static gboolean gimp_operation_find_outline_process (GeglOperation *operation,
+ GeglBuffer *in_buf,
+ const GeglRectangle *roi);
+
+static void
+gimp_operation_find_outline_prepare (GeglOperation *operation);
+
+G_DEFINE_TYPE (GimpOperationFindOutline, gimp_operation_find_outline,
+ GEGL_TYPE_OPERATION_SINK)
+
+#define parent_class gimp_operation_find_outline_parent_class
+
+static void
+gimp_operation_find_outline_class_init (GimpOperationFindOutlineClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
+ GeglOperationSinkClass *sink_class = GEGL_OPERATION_SINK_CLASS (klass);
+
+ object_class->set_property = gimp_operation_find_outline_set_property;
+ object_class->get_property = gimp_operation_find_outline_get_property;
+
+ operation_class->prepare = gimp_operation_find_outline_prepare;
+ operation_class->name = "gimp:find-outline";
+ operation_class->categories = "programming";
+ operation_class->description = "GIMP Outline Finding operation";
+
+ sink_class->process = gimp_operation_find_outline_process;
+ sink_class->needs_full = TRUE;
+
+ g_object_class_install_property (object_class, PROP_POINTS,
+ g_param_spec_pointer ("points",
+ "Points",
+ "A GPtrArray* of struct {gint x, y;} containing the points",
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_THRESHOLD,
+ g_param_spec_double ("threshold",
+ "Threshold",
+ "The threshold for determining the difference between black and white (white >= thres)",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
+ G_PARAM_READWRITE));
+
+ /* Workaround around wrong ROI calculation in GEGL for Sink ops when needs_full is set */
+ g_object_class_install_property (object_class, PROP_X,
+ g_param_spec_int ("x",
+ "X",
+ "The minimal x of the scaning rect",
+ -G_MAXINT, G_MAXINT, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_Y,
+ g_param_spec_int ("y",
+ "Y",
+ "The minimal Y of the scaning rect",
+ -G_MAXINT, G_MAXINT, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_WIDTH,
+ g_param_spec_int ("width",
+ "Width",
+ "The width of the scaning rect",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_HEIGHT,
+ g_param_spec_int ("height",
+ "Height",
+ "The height of the scaning rect",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+gimp_operation_find_outline_init (GimpOperationFindOutline *self)
+{
+}
+
+static void
+gimp_operation_find_outline_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpOperationFindOutline *self = GIMP_OPERATION_FIND_OUTLINE (object);
+
+ switch (property_id)
+ {
+ case PROP_POINTS:
+ g_value_set_pointer (value, self->ptList);
+ break;
+ case PROP_THRESHOLD:
+ g_value_set_double (value, self->threshold);
+ break;
+ case PROP_X:
+ g_value_set_int (value, self->x);
+ break;
+ case PROP_Y:
+ g_value_set_int (value, self->y);
+ break;
+ case PROP_WIDTH:
+ g_value_set_int (value, self->width);
+ break;
+ case PROP_HEIGHT:
+ g_value_set_int (value, self->height);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_operation_find_outline_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpOperationFindOutline *self = GIMP_OPERATION_FIND_OUTLINE (object);
+
+ switch (property_id)
+ {
+ case PROP_POINTS:
+ self->ptList = g_value_get_pointer (value);
+ break;
+ case PROP_THRESHOLD:
+ self->threshold = g_value_get_double (value);
+ break;
+ case PROP_X:
+ self->x = g_value_get_int (value);
+ break;
+ case PROP_Y:
+ self->y = g_value_get_int (value);
+ break;
+ case PROP_WIDTH:
+ self->width = g_value_get_int (value);
+ break;
+ case PROP_HEIGHT:
+ self->height = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+/*******************************************************************/
+/* Real operation logic begins here */
+/*******************************************************************/
+
+/* Define the directions
+ *
+ * 0
+ *
+ * 7 N 1
+ * ^
+ * |
+ * |
+ * 6 W<----+---->E 2
+ * | =====>X
+ * | ||
+ * v ||
+ * 5 S 3 ||
+ * vv
+ * 4 Y
+ */
+typedef enum {
+ D_N = 0, /* 000 */
+ D_NE = 1, /* 001 */
+ D_E = 2, /* 010 */
+ D_SE = 3, /* 011 */
+ D_S = 4, /* 100 */
+ D_SW = 5, /* 101 */
+ D_W = 6, /* 110 */
+ D_NW = 7 /* 111 */
+} OUTLINE_DIRECTION;
+
+#define cwdirection(t) (((t)+1)%8)
+#define ccwdirection(t) (((t)+7)%8)
+#define oppositedirection(t) (((t)+4)%8)
+
+#define isSouth(s) (((s) == D_S) || ((s) == D_SE) || ((s) == D_SW))
+#define isNorth(s) (((s) == D_N) || ((s) == D_NE) || ((s) == D_NW))
+
+#define isEast(s) (((s) == D_NE) || ((s) == D_E) || ((s) == D_SE))
+#define isWest(s) (((s) == D_NW) || ((s) == D_W) || ((s) == D_SW))
+
+typedef struct {
+ gint x, y;
+} SPoint;
+
+/**
+ * Add a COPY of the given point into the array pts. The original point CAN
+ * be freed later!
+ */
+static void
+gimp_operation_find_outline_add_point (GPtrArray* pts, SPoint *pt)
+{
+ printf ("Added %d,%d\n", pt->x, pt->y);
+ if (pts == NULL)
+ return;
+ SPoint *cpy = g_new (SPoint, 1);
+ cpy->x = pt->x;
+ cpy->y = pt->y;
+
+ g_ptr_array_add (pts, cpy);
+}
+
+static inline void
+gimp_operation_find_outline_move (SPoint *pt, OUTLINE_DIRECTION t, SPoint *dest)
+{
+ dest->x = pt->x + (isEast(t) ? 1 : (isWest(t) ? -1 : 0));
+ dest->y = pt->y + (isSouth(t) ? 1 : (isNorth(t) ? -1 : 0));
+}
+
+#define in_range(val,min,max) (((min) <= (val)) && ((val) <= (max)))
+
+static inline gboolean
+gimp_operation_find_outline_is_inside (OutlineProcPrivate *OPP, SPoint *pt)
+{
+ return in_range (pt->x, OPP->xmin, OPP->xmax)
+ && in_range (pt->y, OPP->ymin, OPP->ymax);
+}
+
+#define get_value(OPP,x,y) (((OPP)->im)[((y)-(OPP)->ymin)*(OPP)->rowstride+(x)-(OPP)->xmin])
+#define get_valuePT(OPP,pt) get_value(OPP,(pt)->x,(pt)->y)
+
+static inline gboolean
+gimp_operation_find_outline_is_white (OutlineProcPrivate *OPP, SPoint *pt)
+{
+ return gimp_operation_find_outline_is_inside (OPP, pt) && get_valuePT (OPP,pt) >= OPP->threshold;
+}
+
+/* This function receives a white pixel (pt) and the direction of the movement
+ * that lead to it (prevdirection). It will return the direction leading to the
+ * next white pixel (while following the edges in CW order), and the pixel
+ * itself would be stored in dest.
+ *
+ * The logic is simple:
+ * 1. Try to continue in the same direction that lead us to the current pixel
+ * 2. Dprev = oppposite(prevdirection)
+ * 3. Dnow = cw(Dprev)
+ * 4. While moving to Dnow is white:
+ * 4.1. Dprev = Dnow
+ * 4.2. Dnow = cw(D)
+ * 5. Return the result - moving by Dprev
+ */
+static inline OUTLINE_DIRECTION
+gimp_operation_find_outline_walk_cw (OutlineProcPrivate *OPP,
+ OUTLINE_DIRECTION prevdirection,
+ SPoint *pt,
+ SPoint *dest)
+{
+ OUTLINE_DIRECTION Dprev = oppositedirection(prevdirection);
+ OUTLINE_DIRECTION Dnow = cwdirection (Dprev);
+
+ SPoint ptN, ptP;
+
+ gimp_operation_find_outline_move (pt, Dprev, &ptP);
+ gimp_operation_find_outline_move (pt, Dnow, &ptN);
+
+ while (gimp_operation_find_outline_is_white (OPP, &ptN))
+ {
+ Dprev = Dnow;
+ ptP.x = ptN.x;
+ ptP.y = ptN.y;
+ Dnow = cwdirection (Dprev);
+ gimp_operation_find_outline_move (pt, Dnow, &ptN);
+ }
+
+ dest->x = ptP.x;
+ dest->y = ptP.y;
+ return Dprev;
+}
+
+#define pteq(pt1,pt2) (((pt1)->x == (pt2)->x) && ((pt1)->y == (pt2)->y))
+
+static void
+gimp_operation_find_outline_find_outline_ccw (OutlineProcPrivate *OPP, GPtrArray *pts)
+{
+ gint x = OPP->xmin;
+ gint y;
+ gboolean found = FALSE;
+ SPoint START, pt, ptN;
+ OUTLINE_DIRECTION DIR, DIRN;
+
+ /* First of all try to find a white pixel */
+ for (y = OPP->ymin; y < OPP->ymax; y++)
+ {
+ for (x = OPP->xmin; x < OPP->xmax; x++)
+ {
+ if (get_value (OPP, x, y) >= OPP->threshold)
+ {
+ printf ("Found first white on %d,%d\n",x,y);
+ found = TRUE;
+ break;
+ }
+ }
+ if (found) break;
+ }
+
+ if (!found)
+ return;
+
+ pt.x = START.x = x;
+ pt.y = START.y = y;
+ DIR = D_NW;
+
+ gimp_operation_find_outline_add_point (pts, &START);
+
+ DIRN = gimp_operation_find_outline_walk_cw (OPP, DIR,&pt,&ptN);
+
+ while (! pteq(&ptN,&START))
+ {
+ gimp_operation_find_outline_add_point (pts, &ptN);
+ pt.x = ptN.x;
+ pt.y = ptN.y;
+ DIR = DIRN;
+ DIRN = gimp_operation_find_outline_walk_cw (OPP, DIR,&pt,&ptN);
+ }
+}
+
+static gboolean
+gimp_operation_find_outline_process (GeglOperation *operation,
+ GeglBuffer *input,
+ const GeglRectangle *result)
+{
+ GimpOperationFindOutline *self = GIMP_OPERATION_FIND_OUTLINE (operation);
+ OutlineProcPrivate *OPP = (OutlineProcPrivate *) &GIMP_OPERATION_FIND_OUTLINE(operation)->opp;
+ GeglRectangle rect;
+
+ rect.x = OPP->xmin = self->x;
+ rect.width = self->width;
+ OPP->xmax = self->x + self->width - 1;
+
+ rect.y = OPP->ymin = self->y;
+ rect.height = self->height;
+ OPP->ymax = self->y + self->height - 1;
+
+ OPP->threshold = self->threshold;
+ OPP->im = g_new (gdouble,(rect.width) * rect.height);
+ OPP->rowstride = rect.width;
+
+ gegl_buffer_get (input, 1.0, &rect, babl_format("Y double"), OPP->im, GEGL_AUTO_ROWSTRIDE);
+
+ gimp_operation_find_outline_find_outline_ccw (OPP, self->ptList);
+
+// gint x, y;
+// /* First of all try to find a white pixel */
+// for (y = OPP->ymin; y < OPP->ymax; y++)
+// {
+// for (x = OPP->xmin; x < OPP->xmax; x++)
+// {
+// if (get_value (OPP, x, y) >= OPP->threshold)
+// printf ("1");
+// else
+// printf ("0");
+// }
+// printf("\n");
+// }
+
+ g_free (OPP->im);
+ OPP->im = NULL;
+
+ return TRUE;
+}
+
+static void
+gimp_operation_find_outline_prepare (GeglOperation *operation)
+{
+ printf ("Preparing!\n");
+
+ gegl_operation_set_format (operation, "input", babl_format("Y double"));
+}
diff --git a/app/gegl/gimpoperationfindoutline.h b/app/gegl/gimpoperationfindoutline.h
new file mode 100644
index 0000000..ba80bc9
--- /dev/null
+++ b/app/gegl/gimpoperationfindoutline.h
@@ -0,0 +1,68 @@
+/* GIMP - The GNU Image Manipulation Program
+ *
+ * gimpoperationfindoutline.h
+ * Copyright (C) 2011 Barak Itkin <lightningismyname gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_OPERATION_FIND_OUTLINE_H__
+#define __GIMP_OPERATION_FIND_OUTLINE_H__
+
+
+#include <gegl-plugin.h>
+#include <operation/gegl-operation-sink.h>
+
+
+#define GIMP_TYPE_OPERATION_FIND_OUTLINE (gimp_operation_find_outline_get_type ())
+#define GIMP_OPERATION_FIND_OUTLINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_FIND_OUTLINE, GimpOperationFindOutline))
+#define GIMP_OPERATION_FIND_OUTLINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_FIND_OUTLINE, GimpOperationFindOutlineClass))
+#define GIMP_IS_OPERATION_FIND_OUTLINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_FIND_OUTLINE))
+#define GIMP_IS_OPERATION_FIND_OUTLINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_FIND_OUTLINE))
+#define GIMP_OPERATION_FIND_OUTLINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_FIND_OUTLINE, GimpOperationFindOutlineClass))
+
+
+typedef struct _GimpOperationFindOutlineClass GimpOperationFindOutlineClass;
+
+typedef struct
+{
+ gint xmin, xmax;
+ gint ymin, ymax;
+ gint rowstride;
+ gdouble threshold;
+ gdouble *im;
+} OutlineProcPrivate;
+
+struct _GimpOperationFindOutline
+{
+ GeglOperationSink parent_instance;
+
+ GPtrArray *ptList;
+ gint x, y, width, height;
+ gdouble threshold;
+
+ /* Remains from old versions. Merge with properties above one day */
+ OutlineProcPrivate *opp;
+};
+
+struct _GimpOperationFindOutlineClass
+{
+ GeglOperationSinkClass parent_class;
+};
+
+
+GType gimp_operation_find_outline_get_type (void) G_GNUC_CONST;
+
+
+#endif /* __GIMP_OPERATION_FIND_OUTLINE_H__ */
diff --git a/app/tools/gimpseamlessclonetool.c b/app/tools/gimpseamlessclonetool.c
index 0774ec4..0354d42 100644
--- a/app/tools/gimpseamlessclonetool.c
+++ b/app/tools/gimpseamlessclonetool.c
@@ -213,6 +213,7 @@ gimp_seamless_clone_tool_init (GimpSeamlessCloneTool *self)
self->render_node = NULL;
self->image_map = NULL;
self->translate_op = NULL;
+ self->outline = NULL;
}
static void
@@ -244,6 +245,13 @@ gimp_seamless_clone_tool_control (GimpTool *tool,
sct->translate_op = NULL;
}
+ if (sct->outline)
+ {
+ /* The array was created with a free func, so no need to free */
+ g_ptr_array_free (sct->outline, TRUE);
+ sct->outline = NULL;
+ }
+
if (sct->image_map)
{
gimp_tool_control_set_preserve (tool->control, TRUE);
@@ -328,6 +336,17 @@ gimp_seamless_clone_tool_options_notify (GimpTool *tool,
}
static void
+gimp_seamless_clone_tool_start (GimpSeamlessCloneTool *sct,
+ GimpDisplay *display)
+{
+ DBG_CALL_NAME();
+ GIMP_TOOL(sct)->display = display;
+ gimp_draw_tool_start (GIMP_DRAW_TOOL (sct), display);
+ // TODO free and update stuff
+
+
+}
+static void
gimp_seamless_clone_tool_button_press (GimpTool *tool,
const GimpCoords *coords,
guint32 time,
@@ -337,8 +356,16 @@ gimp_seamless_clone_tool_button_press (GimpTool *tool,
{
GimpSeamlessCloneTool *sct = GIMP_SEAMLESS_CLONE_TOOL (tool);
+ DBG_CALL_NAME();
+
+ if (tool->display != display)
+ {
+ gimp_seamless_clone_tool_start (sct, display);
+ }
+
if (sct->state == SEAMLESS_CLONE_STATE_NOTHING)
{
+ gimp_draw_tool_start (GIMP_DRAW_TOOL (sct), display);
if (! sct->render_node)
{
gimp_seamless_clone_tool_create_render_node (sct);
@@ -474,11 +501,15 @@ gimp_seamless_clone_tool_cursor_update (GimpTool *tool,
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
+typedef struct {
+ gint x, y;
+} SPoint;
+
static void
gimp_seamless_clone_tool_draw (GimpDrawTool *draw_tool)
{
GimpSeamlessCloneTool *sct = GIMP_SEAMLESS_CLONE_TOOL (draw_tool);
-
+ gint i;
GimpCanvasGroup *stroke_group;
DBG_CALL_NAME();
@@ -487,23 +518,36 @@ gimp_seamless_clone_tool_draw (GimpDrawTool *draw_tool)
gimp_draw_tool_push_group (draw_tool, stroke_group);
+ if (sct->outline)
+ {
+ printf ("Outline exists!\n");
+ if (sct->state != SEAMLESS_CLONE_STATE_MOTION)
+ for (i = 0; i < sct->outline->len; i++)
+ {
+ SPoint *n1 = (SPoint*)g_ptr_array_index (sct->outline, i);
+ SPoint *n2 = (SPoint*)g_ptr_array_index (sct->outline, (i+1) % sct->outline->len);
+ gimp_draw_tool_add_line (draw_tool, n1->x+sct->paste_x, n1->y+sct->paste_y, n2->x+sct->paste_x, n2->y+sct->paste_y);
+ }
+ }
+
/* Draw the corner of the paste */
if (sct->state == SEAMLESS_CLONE_STATE_MOTION)
gimp_draw_tool_add_crosshair (draw_tool,
- (gdouble)(sct->paste_x + (gint)(sct->cursor_x - sct->movement_start_x)),
- (gdouble)(sct->paste_y + (gint)(sct->cursor_y - sct->movement_start_y)));
+ (gdouble)(sct->paste_x + (gint)(sct->cursor_x - sct->movement_start_x + sct->paste_w / 2)),
+ (gdouble)(sct->paste_y + (gint)(sct->cursor_y - sct->movement_start_y + sct->paste_h / 2)));
gimp_draw_tool_pop_group (draw_tool);
}
-/* TODO - extract this logic for general gimp->gegl buffer conversion */
+/* TODO - extract this logic for general gimp->gegl buffer conversion.
+ * Note this also computes and saves the outline of the buffer */
static void
gimp_buffer_to_gegl_buffer_with_progress (GimpSeamlessCloneTool *sct)
{
GimpProgress *progress;
GeglNode *gegl;
GeglNode *input;
- GeglNode *output;
+ GeglNode *output, *outline;
GeglProcessor *processor;
GeglBuffer *buffer;
gdouble value;
@@ -535,9 +579,20 @@ gimp_buffer_to_gegl_buffer_with_progress (GimpSeamlessCloneTool *sct)
"buffer", &buffer,
NULL);
+ sct->outline = g_ptr_array_new_with_free_func (g_free);
+ outline = gegl_node_new_child (gegl,
+ "operation", "gimp:find-outline",
+ "points", sct->outline,
+ "width", gimp_buffer_get_width (gimpbuf),
+ "height", gimp_buffer_get_height (gimpbuf),
+ NULL);
+
gegl_node_connect_to (input, "output",
output, "input");
+ gegl_node_connect_to (input, "output",
+ outline, "input");
+
processor = gegl_node_new_processor (output, NULL);
while (gegl_processor_work (processor, &value))
@@ -551,6 +606,21 @@ gimp_buffer_to_gegl_buffer_with_progress (GimpSeamlessCloneTool *sct)
gegl_processor_destroy (processor);
+
+ processor = gegl_node_new_processor (outline, NULL);
+
+ while (gegl_processor_work (processor, &value))
+ {
+ if (progress)
+ gimp_progress_set_value (progress, value);
+ }
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gegl_processor_destroy (processor);
+
+
sct->paste_buf = buffer;
tempR = * gegl_buffer_get_extent (buffer);
sct->paste_w = tempR.width;
diff --git a/app/tools/gimpseamlessclonetool.h b/app/tools/gimpseamlessclonetool.h
index ace2f58..dedfb35 100644
--- a/app/tools/gimpseamlessclonetool.h
+++ b/app/tools/gimpseamlessclonetool.h
@@ -65,6 +65,8 @@ struct _GimpSeamlessCloneTool
GeglNode *translate_op;
GimpImageMap *image_map; /* Used for preview of the resulting drawable */
+
+ GPtrArray *outline;
};
#define gimp_seamless_clone_coords_in_paste(sct,c) \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]