[gegl/soc-2011-seamless-clone] Introduce a new WIP two-step seamless-cloning procedure
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-seamless-clone] Introduce a new WIP two-step seamless-cloning procedure
- Date: Sun, 14 Aug 2011 17:33:00 +0000 (UTC)
commit 0edcce49db573f3f29cd123959f3d9dc9906a6d8
Author: Barak Itkin <lightningismyname gmail com>
Date: Sun Aug 14 20:25:55 2011 +0300
Introduce a new WIP two-step seamless-cloning procedure
operations/common/seamless-clone/Makefile.am | 17 +-
operations/common/seamless-clone/find-outline.c | 4 +-
operations/common/seamless-clone/find-outline.h | 2 +-
.../common/seamless-clone/seamless-clone-prepare.c | 100 ++++++++
.../common/seamless-clone/seamless-clone-render.c | 241 ++++++++++++++++++++
operations/common/seamless-clone/seamless-clone.h | 24 ++-
6 files changed, 371 insertions(+), 17 deletions(-)
---
diff --git a/operations/common/seamless-clone/Makefile.am b/operations/common/seamless-clone/Makefile.am
index 30d5b39..9f36646 100644
--- a/operations/common/seamless-clone/Makefile.am
+++ b/operations/common/seamless-clone/Makefile.am
@@ -2,21 +2,20 @@ SUBDIRS = poly2tri-c
include $(top_srcdir)/operations/Makefile-common.am
-LIBS = $(op_libs)
+AM_LDFLAGS += $(op_libs) poly2tri-c/libpoly2tri-c.la
-seamless_clone_la_SOURCES = \
- make-mesh.c \
+sc_common_files = \
+ make-mesh.c \
make-mesh.h \
find-outline.c \
find-outline.h \
- seamless-clone.c \
seamless-clone.h
-seamless_clone_la_LIBADD = $(op_libs) poly2tri-c/libpoly2tri-c.la
-seamless_clone_la_CFLAGS = $(AM_CFLAGS) $(BABL_CFLAGS) $(GLIB_CFLAGS)
+seamless_clone_la_SOURCES = seamless-clone.c $(sc_common_files)
+seamless_clone_render_la_SOURCES = seamless-clone-render.c $(sc_common_files)
+seamless_clone_prepare_la_SOURCES = seamless-clone-prepare.c $(sc_common_files)
opdir = $(libdir)/gegl- GEGL_API_VERSION@
-op_LTLIBRARIES = seamless-clone.la
-AM_CPPFLAGS += \
- -I$(top_srcdir)/operations/common
+op_LTLIBRARIES = seamless-clone.la seamless-clone-render.la seamless-clone-prepare.la
+Introduce a new WIP two-step seamless-cloning procedure
diff --git a/operations/common/seamless-clone/find-outline.c b/operations/common/seamless-clone/find-outline.c
index eef86ab..ddf3d49 100644
--- a/operations/common/seamless-clone/find-outline.c
+++ b/operations/common/seamless-clone/find-outline.c
@@ -167,8 +167,8 @@ outline_walk_cw (GeglRectangle *rect,
#define pteq(pt1,pt2) (((pt1)->x == (pt2)->x) && ((pt1)->y == (pt2)->y))
GPtrArray*
-sc_outline_find_ccw (GeglRectangle *rect,
- GeglBuffer *pixels)
+sc_outline_find_ccw (const GeglRectangle *rect,
+ const GeglBuffer *pixels)
{
Babl *format = babl_format("RGBA float");
GPtrArray *points = g_ptr_array_new ();
diff --git a/operations/common/seamless-clone/find-outline.h b/operations/common/seamless-clone/find-outline.h
index a708c54..5eb44f5 100644
--- a/operations/common/seamless-clone/find-outline.h
+++ b/operations/common/seamless-clone/find-outline.h
@@ -33,7 +33,7 @@ typedef struct {
*/
typedef GPtrArray ScOutline;
-ScOutline* sc_outline_find_ccw (GeglRectangle *rect, GeglBuffer *pixels);
+ScOutline* sc_outline_find_ccw (const GeglRectangle *rect, const GeglBuffer *pixels);
void sc_outline_free (ScOutline *self);
diff --git a/operations/common/seamless-clone/seamless-clone-prepare.c b/operations/common/seamless-clone/seamless-clone-prepare.c
new file mode 100644
index 0000000..9aa399c
--- /dev/null
+++ b/operations/common/seamless-clone/seamless-clone-prepare.c
@@ -0,0 +1,100 @@
+/* This file is an image processing operation for GEGL
+ *
+ * seamless-clone-prepare.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/>.
+ */
+
+/*
+ * This is part 1 of 2 in the process of real-time seamless cloning.
+ * This operation takes a paste to be seamlessly cloned, and a property
+ * which is a pointer to a pointer. Through that pointer, the operation
+ * should return a data structure that is to be passed to the next
+ * operations.
+ */
+
+#ifdef GEGL_CHANT_PROPERTIES
+gegl_chant_pointer (result, _("result"),
+ _("A pointer to a pointer (gpointer*) to store the result in"))
+#else
+
+#define GEGL_CHANT_TYPE_SINK
+#define GEGL_CHANT_C_FILE "seamless-clone-prepare.c"
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include "gegl-chant.h"
+
+#include "poly2tri-c/poly2tri.h"
+#include "poly2tri-c/refine/triangulation.h"
+#include "poly2tri-c/render/mesh-render.h"
+#include "seamless-clone.h"
+
+static void
+prepare (GeglOperation *operation)
+{
+ Babl *format = babl_format ("R'G'B'A float");
+
+ gegl_operation_set_format (operation, "input", format);
+}
+
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ const GeglRectangle *roi)
+{
+ ScPreprocessResult *result = sc_preprocess_new ();
+
+ /* First, find the paste outline */
+ result->outline = sc_outline_find_ccw (roi, input);
+
+ /* Then, Generate the mesh */
+ result->mesh = sc_make_fine_mesh (result->outline, &result->mesh_bounds);
+
+ /* Finally, Generate the mesh sample list for each point */
+ result->sampling = sc_mesh_sampling_compute (result->outline, result->mesh);
+
+ /* If caching of UV is desired, it shold be done here, and possibly
+ * by using a regular operation rather than a sink one, so that we can
+ * output UV coords */
+
+ GEGL_CHANT_PROPERTIES (operation) -> result = result;
+
+ /*
+ sc_mesh_sampling_free (mesh_sampling);
+ p2tr_triangulation_free (mesh);
+ sc_outline_free (outline);
+ */
+
+ return TRUE;
+}
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
+ GeglOperationSinkClass *sink_class = GEGL_OPERATION_SINK_CLASS (klass);
+
+ operation_class->prepare = prepare;
+ operation_class->name = "gegl:seamless-clone-prepare";
+ operation_class->categories = "programming";
+ operation_class->description = _("Seamless cloning preprocessing operation");
+
+ sink_class->process = process;
+ sink_class->needs_full = TRUE;
+}
+
+#endif
diff --git a/operations/common/seamless-clone/seamless-clone-render.c b/operations/common/seamless-clone/seamless-clone-render.c
new file mode 100644
index 0000000..6c06ab9
--- /dev/null
+++ b/operations/common/seamless-clone/seamless-clone-render.c
@@ -0,0 +1,241 @@
+/* This file is an image processing operation for GEGL
+ *
+ * seamless-clone-render.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/>.
+ */
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_int (xoff, "xoff", G_MININT, G_MAXINT, 0,
+ _("The x offset to apply to the paste"))
+
+gegl_chant_int (yoff, "yoff", G_MININT, G_MAXINT, 0,
+ _("The y offset to apply to the paste"))
+
+gegl_chant_pointer (prepare, _("prepare"),
+ _("The pointer returned from the seamless-clone-prepare operation, applied on the aux buf"))
+
+#else
+
+#define GEGL_CHANT_TYPE_COMPOSER
+#define GEGL_CHANT_C_FILE "seamless-clone-render.c"
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include "gegl-chant.h"
+
+#include "poly2tri-c/poly2tri.h"
+#include "poly2tri-c/refine/triangulation.h"
+#include "poly2tri-c/render/mesh-render.h"
+#include "seamless-clone.h"
+
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *region)
+{
+ GeglRectangle *temp = NULL;
+ GeglRectangle result;
+
+ if (g_strcmp0 (input_pad, "input") || g_strcmp0 (input_pad, "aux"))
+ temp = gegl_operation_source_get_bounding_box (operation, input_pad);
+ else
+ g_warning ("seamless-clone::Unknown input pad \"%s\"\n", input_pad);
+
+ if (temp != NULL)
+ result = *temp;
+ else
+ {
+ result.width = result.height = 0;
+ }
+
+ return result;
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+ Babl *format = babl_format ("R'G'B'A float");
+
+ gegl_operation_set_format (operation, "input", format);
+ gegl_operation_set_format (operation, "aux", format);
+ gegl_operation_set_format (operation, "output", format);
+}
+
+
+typedef struct {
+ GeglBuffer *aux_buf;
+ GeglBuffer *input_buf;
+ ScMeshSampling *sampling;
+ GHashTable *pt2col;
+
+ /* Offset to be applied to the paste */
+ gint xoff, yoff;
+} ScColorComputeInfo;
+
+static void
+sc_point_to_color_func (P2tRPoint *point,
+ gfloat *dest,
+ gpointer cci_p)
+{
+ ScColorComputeInfo *cci = (ScColorComputeInfo*) cci_p;
+ ScSampleList *sl = g_hash_table_lookup (cci->sampling, point);
+ gfloat aux_c[4], input_c[4], dest_c[3] = {0, 0, 0};
+ gint i;
+ gdouble weightT = 0;
+ guint N = sl->points->len;
+ gfloat *col_cpy;
+
+ Babl *format = babl_format ("R'G'B'A float");
+
+ if ((col_cpy = g_hash_table_lookup (cci->pt2col, point)) != NULL)
+ {
+ dest[0] = col_cpy[0];
+ dest[1] = col_cpy[1];
+ dest[2] = col_cpy[2];
+ dest[3] = col_cpy[3];
+ return;
+ }
+ else
+ {
+ col_cpy = g_new (gfloat, 4);
+ g_hash_table_insert (cci->pt2col, point, col_cpy);
+ }
+
+ for (i = 0; i < N; i++)
+ {
+ ScPoint *pt = g_ptr_array_index (sl->points, i);
+ gdouble weight = g_array_index (sl->weights, gdouble, i);
+
+ gegl_buffer_sample (cci->aux_buf, pt->x, pt->y, NULL, aux_c, format, GEGL_INTERPOLATION_NEAREST);
+ /* Sample the BG with the offset */
+ gegl_buffer_sample (cci->input_buf, pt->x + cci->xoff, pt->y + cci->yoff, NULL, input_c, format, GEGL_INTERPOLATION_NEAREST);
+
+ dest_c[0] += weight * (input_c[0] - aux_c[0]);
+ dest_c[1] += weight * (input_c[1] - aux_c[1]);
+ dest_c[2] += weight * (input_c[2] - aux_c[2]);
+ weightT += weight;
+ }
+
+ col_cpy[0] = dest[0] = dest_c[0] / weightT;
+ col_cpy[1] = dest[1] = dest_c[1] / weightT;
+ col_cpy[2] = dest[2] = dest_c[2] / weightT;
+ col_cpy[3] = dest[3] = 1;
+}
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *output,
+ const GeglRectangle *result)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ ScPreprocessResult *spr = o->prepare;
+
+ gfloat *out_raw, *pixel;
+ gdouble x, y;
+
+ GeglRectangle aux_rect = *gegl_operation_source_get_bounding_box (operation, "aux");
+ GeglRectangle to_render;
+
+ ScColorComputeInfo cci;
+ P2tRImageConfig imcfg;
+
+ Babl *format = babl_format("R'G'B'A float");
+
+ if (spr == NULL)
+ {
+ g_warning ("No preprocessing result given. Stop.");
+ return FALSE;
+ }
+
+ /* The location of the aux will actually be computed with an offset */
+ aux_rect.x += o->xoff;
+ aux_rect.y += o->yoff;
+
+ /* We only need to render the intersection of the mesh bounds and the
+ * desired output */
+ gegl_rectangle_intersect (&to_render, result, &aux_rect);
+
+ /* Alocate the output buffer */
+ out_raw = g_new (gfloat, 4 * to_render.width * to_render.height);
+
+ /* Render the mesh into it */
+ cci.aux_buf = aux;
+ cci.input_buf = input;
+ cci.sampling = spr->sampling;
+ cci.pt2col = (gpointer) g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+
+ /* In order to sample colors correctly, the sampling function will
+ * need to know the offset */
+ cci.xoff = o->xoff;
+ cci.yoff = o->yoff;
+
+ /* Render as if there is no offset, since the mesh has no offset */
+ imcfg.min_x = to_render.x - o->xoff;
+ imcfg.min_y = to_render.y - o->yoff;
+ imcfg.step_x = imcfg.step_y = 1;
+ imcfg.x_samples = to_render.width;
+ imcfg.y_samples = to_render.height;
+ imcfg.cpp = 4;
+
+ p2tr_mesh_render_scanline (spr->mesh, out_raw, &imcfg, sc_point_to_color_func, &cci);
+
+ pixel = out_raw;
+
+ /* Note that when composing the aux, we still ignore the offset */
+ pixel = out_raw;
+ for (y = 0; y < imcfg.y_samples; y++)
+ for (x = 0; x < imcfg.x_samples; x++)
+ {
+ gfloat aux_c[4];
+ gdouble Px = imcfg.min_x + x * imcfg.step_x;
+ gdouble Py = imcfg.min_y + y * imcfg.step_y;
+ gegl_buffer_sample (aux, Px, Py, NULL, aux_c, format, GEGL_INTERPOLATION_NEAREST);
+ *pixel++ += aux_c[0];
+ *pixel++ += aux_c[1];
+ *pixel++ += aux_c[2];
+ pixel++;// += 0;//aux_c[3];
+ }
+
+ /* Now, finally commit the result. Note that we commit in the
+ * offsetted to_result area! */
+ gegl_buffer_set (output, &to_render, babl_format("R'G'B'A float"), out_raw, GEGL_AUTO_ROWSTRIDE);
+
+ g_free (out_raw);
+ g_hash_table_destroy (cci.pt2col);
+
+ return TRUE;
+}
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
+ GeglOperationComposerClass *composer_class = GEGL_OPERATION_COMPOSER_CLASS (klass);
+
+ operation_class->prepare = prepare;
+ operation_class->name = "gegl:seamless-clone-render";
+ operation_class->categories = "programming";
+ operation_class->description = "Seamless cloning rendering operation";
+ operation_class->get_required_for_output = get_required_for_output;
+
+ composer_class->process = process;
+}
+
+
+#endif
diff --git a/operations/common/seamless-clone/seamless-clone.h b/operations/common/seamless-clone/seamless-clone.h
index 88d41f0..96254a8 100644
--- a/operations/common/seamless-clone/seamless-clone.h
+++ b/operations/common/seamless-clone/seamless-clone.h
@@ -20,15 +20,29 @@
#ifndef __SEAMLESS_CLONE_H__
#define __SEAMLESS_CLONE_H__
-#define TO_CAIRO(col) ((col)/2+0.5)
-//#define FROM_CAIRO(col) (((col)-0.5)*2)
-//#define TO_CAIRO(col) (col)
-#define FROM_CAIRO(col) ((col - 128)*2)
-
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include "find-outline.h"
#include "make-mesh.h"
+typedef struct {
+ ScOutline *outline;
+ P2tRTriangulation *mesh;
+ GeglRectangle mesh_bounds;
+ ScMeshSampling *sampling;
+} ScPreprocessResult;
+
+#define sc_preprocess_new() (g_new0 (ScPreprocessResult, 1))
+
+//inline void
+//sc_preprocess_result_free (ScPreprocessResult *self)
+//{
+// sc_mesh_sampling_free (self->sampling);
+// p2tr_triangulation_free (self->mesh);
+// sc_outline_free (self->outline);
+//
+// g_free (self);
+//}
+
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]