[gegl/soc-2011-seamless-clone: 20/49] Remove code duplication between the seamless-clone operations
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-seamless-clone: 20/49] Remove code duplication between the seamless-clone operations
- Date: Sat, 29 Sep 2012 20:28:32 +0000 (UTC)
commit a0c44930b74838604c0a3807724562ae71158528
Author: Barak Itkin <lightningismyname gmail com>
Date: Thu Mar 29 12:20:26 2012 +0200
Remove code duplication between the seamless-clone operations
operations/common/seamless-clone/Makefile.am | 7 +-
operations/common/seamless-clone/find-outline.c | 2 -
.../common/seamless-clone/seamless-clone-common.c | 255 ++++++++++++++++++++
.../common/seamless-clone/seamless-clone-common.h | 65 +++++
.../common/seamless-clone/seamless-clone-prepare.c | 45 +----
.../common/seamless-clone/seamless-clone-render.c | 156 +------------
operations/common/seamless-clone/seamless-clone.c | 177 +-------------
operations/common/seamless-clone/seamless-clone.h | 4 +-
8 files changed, 338 insertions(+), 373 deletions(-)
---
diff --git a/operations/common/seamless-clone/Makefile.am b/operations/common/seamless-clone/Makefile.am
index e3fe614..88df97e 100644
--- a/operations/common/seamless-clone/Makefile.am
+++ b/operations/common/seamless-clone/Makefile.am
@@ -5,11 +5,12 @@ include $(top_srcdir)/operations/Makefile-common.am
AM_LDFLAGS += $(op_libs) poly2tri-c/libpoly2tri-c.la
sc_common_files = \
- make-mesh.c \
- make-mesh.h \
+ make-mesh.c \
+ make-mesh.h \
find-outline.c \
find-outline.h \
- seamless-clone.h
+ seamless-clone-common.c \
+ seamless-clone-common.h
seamless_clone_la_SOURCES = seamless-clone.c $(sc_common_files)
seamless_clone_render_la_SOURCES = seamless-clone-render.c $(sc_common_files)
diff --git a/operations/common/seamless-clone/find-outline.c b/operations/common/seamless-clone/find-outline.c
index 26dc93e..9f0f7a9 100644
--- a/operations/common/seamless-clone/find-outline.c
+++ b/operations/common/seamless-clone/find-outline.c
@@ -213,8 +213,6 @@ sc_outline_find_ccw (const GeglRectangle *rect,
DIRN = outline_walk_cw (rect, pixels, format, DIR,&pt,&ptN);
}
- g_debug ("Outline has %d points", points->len);
-
return points;
}
diff --git a/operations/common/seamless-clone/seamless-clone-common.c b/operations/common/seamless-clone/seamless-clone-common.c
new file mode 100644
index 0000000..00366e8
--- /dev/null
+++ b/operations/common/seamless-clone/seamless-clone-common.c
@@ -0,0 +1,255 @@
+/* This file is an image processing operation for GEGL
+ *
+ * seamless-clone-common.c
+ * Copyright (C) 2012 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 "seamless-clone-common.h"
+#include "make-mesh.h"
+
+static GeglBuffer*
+sc_compute_UVT_cache (P2tRTriangulation *mesh,
+ const GeglRectangle *area)
+{
+ GeglBuffer *uvt;
+ GeglBufferIterator *iter;
+ P2tRImageConfig config;
+
+ uvt = gegl_buffer_new (area, SC_BABL_UVT_FORMAT);
+
+ iter = gegl_buffer_iterator_new (uvt, area, SC_BABL_UVT_FORMAT,
+ GEGL_BUFFER_WRITE);
+
+ config.step_x = config.step_y = 1;
+ config.cpp = 4; /* Not that it will be used, but it won't harm */
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ config.min_x = iter->roi[0].x;
+ config.min_y = iter->roi[0].y;
+ config.x_samples = iter->roi[0].width;
+ config.y_samples = iter->roi[0].height;
+ p2tr_mesh_render_cache_uvt_exact (mesh,
+ (P2tRuvt*) iter->data[0],
+ iter->length,
+ &config);
+ }
+
+ /* No need to free the iterator */
+
+ return uvt;
+}
+
+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;
+
+ 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;
+ }
+
+ col_cpy = g_new (gfloat, 4);
+ g_hash_table_insert (cci->pt2col, point, col_cpy);
+
+ Babl *format = babl_format ("R'G'B'A float");
+
+ for (i = 0; i < N; i++)
+ {
+ ScPoint *pt = g_ptr_array_index (sl->points, i);
+ gdouble weight = g_array_index (sl->weights, gdouble, i);
+
+ /* The original outline point is on (pt->x,pt->y) in terms of mesh
+ * coordinates. But, since we are translating, it's location in
+ * background coordinates is (pt->x + cci->x, pt->y + cci->y)
+ */
+
+ /* If the outline point is outside the background, then we can't
+ * compute a propper difference there. So, don't add it to the
+ * sampling */
+#define sc_rect_contains(rect,x0,y0) \
+ (((x0) >= (rect).x) && ((x0) < (rect).x + (rect).width) \
+ && ((y0) >= (rect).y) && ((y0) < (rect).y + (rect).height))
+
+ if (! sc_rect_contains (cci->bg_rect, pt->x + cci->xoff, pt->y + cci->yoff)) { continue; }
+
+#undef sc_rect_contains
+
+ gegl_buffer_sample (cci->fg_buf, pt->x, pt->y, NULL, aux_c, format, GEGL_SAMPLER_NEAREST);
+ /* Sample the BG with the offset */
+ gegl_buffer_sample (cci->bg_buf, pt->x + cci->xoff, pt->y + cci->yoff, NULL, input_c, format, GEGL_SAMPLER_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;
+}
+
+gboolean
+sc_render_seamless (GeglBuffer *bg,
+ GeglBuffer *fg,
+ int fg_xoff,
+ int fg_yoff,
+ GeglBuffer *dest,
+ const GeglRectangle *dest_rect,
+ const ScCache *cache)
+{
+ GeglRectangle fg_rect, to_render;
+
+ ScColorComputeInfo mesh_render_info;
+ GeglBufferIterator *iter;
+ int out_index, uvt_index, fg_index;
+
+ Babl *format = babl_format("R'G'B'A float");
+
+ if (cache == NULL)
+ {
+ g_warning ("No preprocessing result given. Stop.");
+ return FALSE;
+ }
+
+ fg_rect = *gegl_buffer_get_extent (fg);
+
+ /* The location of the aux will actually be computed with an offset */
+ fg_rect.x += fg_xoff;
+ fg_rect.y += fg_yoff;
+
+ /* We only need to render the intersection of the mesh bounds and the
+ * desired output */
+ gegl_rectangle_intersect (&to_render, dest_rect, &fg_rect);
+
+ /* Render the mesh into it */
+ mesh_render_info.fg_buf = fg;
+ mesh_render_info.bg_buf = bg;
+ mesh_render_info.sampling = cache->sampling;
+ mesh_render_info.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 */
+ mesh_render_info.xoff = fg_xoff;
+ mesh_render_info.yoff = fg_yoff;
+ mesh_render_info.bg_rect = *gegl_buffer_get_extent (bg);
+
+ /* Iterate over the output buffer, while synching with the paste and
+ * the cache */
+ iter = gegl_buffer_iterator_new (dest, &to_render, format,
+ GEGL_BUFFER_WRITE);
+ out_index = 0;
+
+ uvt_index = gegl_buffer_iterator_add (iter,
+ cache->uvt,
+ &to_render,
+ SC_BABL_UVT_FORMAT,
+ GEGL_BUFFER_READ);
+
+ fg_index = gegl_buffer_iterator_add (iter,
+ fg,
+ &to_render,
+ format,
+ GEGL_BUFFER_READ);
+
+ while (gegl_buffer_iterator_next (iter))
+ {
+ P2tRImageConfig imcfg;
+ float *out_raw, *fg_raw;
+ P2tRuvt *uvt_raw;
+ int x, y;
+
+ imcfg.min_x = iter->roi[out_index].x;
+ imcfg.min_y = iter->roi[out_index].y;
+ imcfg.step_x = imcfg.step_y = 1;
+ imcfg.x_samples = iter->roi[out_index].width;
+ imcfg.y_samples = iter->roi[out_index].height;
+ imcfg.cpp = 4;
+
+ out_raw = (gfloat*)iter->data[out_index];
+ uvt_raw = (P2tRuvt*)iter->data[uvt_index];
+ fg_raw = (gfloat*)iter->data[fg_index];
+
+ p2tr_mesh_render_scanline2 (uvt_raw, out_raw, &imcfg, sc_point_to_color_func, &mesh_render_info);
+
+ for (y = 0; y < imcfg.y_samples; y++)
+ {
+ for (x = 0; x < imcfg.x_samples; x++)
+ {
+ out_raw[0] += fg_raw[0];
+ out_raw[1] += fg_raw[1];
+ out_raw[2] += fg_raw[2];
+
+ out_raw += 4;
+ fg_raw += 4;
+ }
+ }
+ }
+ g_hash_table_destroy (mesh_render_info.pt2col);
+
+ return TRUE;
+}
+
+ScCache*
+sc_generate_cache (GeglBuffer *fg,
+ const GeglRectangle *extents,
+ int max_refine_steps)
+{
+ ScOutline *outline;
+ ScCache *result = g_new0 (ScCache, 1);
+
+ /* Find an outline around the area of the paste */
+ outline = sc_outline_find_ccw (extents, fg);
+ /* Create a fine mesh from the polygon defined by that outline */
+ result->mesh = sc_make_fine_mesh (outline, &result->mesh_bounds,
+ max_refine_steps);
+ /* Now compute the list of points to sample in order to define the
+ * color of each triangulation vertex */
+ result->sampling = sc_mesh_sampling_compute (outline, result->mesh);
+
+ /* We need the outline since the sampling relies on it's points */
+ result->outline = outline;
+
+ /* For each pixel inside the paste area, cache which triangle contains
+ * it, and the triangle interpolation parameters for that point */
+ result->uvt = sc_compute_UVT_cache (result->mesh,
+ &result->mesh_bounds);
+ return result;
+}
+
+void
+sc_cache_free (ScCache *cache)
+{
+ gegl_buffer_destroy(cache->uvt);
+ sc_mesh_sampling_free (cache->sampling);
+ p2tr_triangulation_free (cache->mesh);
+ sc_outline_free (cache->outline);
+ g_free (cache);
+}
diff --git a/operations/common/seamless-clone/seamless-clone-common.h b/operations/common/seamless-clone/seamless-clone-common.h
new file mode 100644
index 0000000..7982008
--- /dev/null
+++ b/operations/common/seamless-clone/seamless-clone-common.h
@@ -0,0 +1,65 @@
+/* This file is an image processing operation for GEGL
+ *
+ * seamless-clone-common.h
+ * Copyright (C) 2012 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 __SEAMLESS_CLONE_COMMON_H__
+#define __SEAMLESS_CLONE_COMMON_H__
+
+#include "poly2tri-c/poly2tri.h"
+#include "poly2tri-c/refine/triangulation.h"
+#include "poly2tri-c/render/mesh-render.h"
+
+#include "find-outline.h"
+#include "make-mesh.h"
+
+typedef struct {
+ GeglRectangle bg_rect;
+ GeglBuffer *fg_buf;
+ GeglBuffer *bg_buf;
+ ScMeshSampling *sampling;
+ GHashTable *pt2col;
+ int xoff;
+ int yoff;
+} ScColorComputeInfo;
+
+typedef struct {
+ GeglRectangle mesh_bounds;
+ P2tRTriangulation *mesh;
+ ScMeshSampling *sampling;
+ GeglBuffer *uvt;
+ ScOutline *outline;
+} ScCache;
+
+gboolean sc_render_seamless (GeglBuffer *bg,
+ GeglBuffer *fg,
+ int fg_xoff,
+ int fg_yoff,
+ GeglBuffer *dest,
+ const GeglRectangle *dest_rect,
+ const ScCache *cache);
+
+ScCache* sc_generate_cache (GeglBuffer *fg,
+ const GeglRectangle *extents,
+ int max_refine_steps);
+
+void sc_cache_free (ScCache *cache);
+
+#define SC_BABL_UVT_TYPE (babl_type_new ("uvt", "bits", sizeof (P2tRuvt) * 8, NULL))
+#define SC_BABL_UVT_FORMAT (babl_format_n (SC_BABL_UVT_TYPE, 3))
+
+#endif
diff --git a/operations/common/seamless-clone/seamless-clone-prepare.c b/operations/common/seamless-clone/seamless-clone-prepare.c
index 2d5ff89..1cf0946 100644
--- a/operations/common/seamless-clone/seamless-clone-prepare.c
+++ b/operations/common/seamless-clone/seamless-clone-prepare.c
@@ -42,7 +42,7 @@ gegl_chant_int (max_refine_steps, _("Refinement Steps"), 0, 100000.0, 2000,
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include "poly2tri-c/render/mesh-render.h"
-#include "seamless-clone.h"
+#include "seamless-clone-common.h"
static void
prepare (GeglOperation *operation)
@@ -64,56 +64,15 @@ process (GeglOperation *operation,
GeglBuffer *input,
const GeglRectangle *roi)
{
- ScPreprocessResult *result = sc_preprocess_new ();
gpointer *dest = GEGL_CHANT_PROPERTIES (operation) -> result;
- GeglBuffer *uvt;
- GeglBufferIterator *iter;
- P2tRImageConfig config;
-
if (dest == NULL)
{
return FALSE;
}
-
- /* 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, GEGL_CHANT_PROPERTIES (operation) -> max_refine_steps);
-
- /* 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 */
- result->uvt = gegl_buffer_new (roi, babl_uvt_format);
-
- iter = gegl_buffer_iterator_new (result->uvt, roi, NULL, GEGL_BUFFER_WRITE);
-
- config.step_x = config.step_y = 1;
- config.cpp = 4; /* Not that it will be used, but it won't harm */
-
- while (gegl_buffer_iterator_next (iter))
- {
- config.min_x = iter->roi[0].x;
- config.min_y = iter->roi[0].y;
- config.x_samples = iter->roi[0].width;
- config.y_samples = iter->roi[0].height;
- p2tr_mesh_render_cache_uvt_exact (result->mesh, (P2tRuvt*) iter->data[0], iter->length, &config);
- }
- /* No need to free the iterator */
- *dest = result;
+ *dest = sc_generate_cache (input, roi, GEGL_CHANT_PROPERTIES (operation) -> max_refine_steps);
- /*
- sc_mesh_sampling_free (mesh_sampling);
- p2tr_triangulation_free (mesh);
- sc_outline_free (outline);
- gegl_buffer_destroy (uvt);
- */
-
return TRUE;
}
diff --git a/operations/common/seamless-clone/seamless-clone-render.c b/operations/common/seamless-clone/seamless-clone-render.c
index defc1de..a3e51ab 100644
--- a/operations/common/seamless-clone/seamless-clone-render.c
+++ b/operations/common/seamless-clone/seamless-clone-render.c
@@ -40,7 +40,7 @@ gegl_chant_pointer (prepare, _("prepare"),
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include "poly2tri-c/render/mesh-render.h"
-#include "seamless-clone.h"
+#include "seamless-clone-common.h"
static GeglRectangle
get_required_for_output (GeglOperation *operation,
@@ -75,83 +75,6 @@ prepare (GeglOperation *operation)
gegl_operation_set_format (operation, "output", format);
}
-
-typedef struct {
- GeglBuffer *aux_buf;
- GeglBuffer *input_buf;
- ScMeshSampling *sampling;
- GHashTable *pt2col;
- GeglRectangle bg_rect;
- /* Offset to be applied to the paste */
- gint x, y;
-} 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);
-
- /* The original outline point is on (pt->x,pt->y) in terms of mesh
- * coordinates. But, since we are translating, it's location in
- * background coordinates is (pt->x + cci->x, pt->y + cci->y)
- */
-
- /* If the outline point is outside the background, then we can't
- * compute a propper difference there. So, don't add it to the
- * sampling */
-#define sc_rect_contains(rect,x0,y0) \
- (((x0) >= (rect).x) && ((x0) < (rect).x + (rect).width) \
- && ((y0) >= (rect).y) && ((y0) < (rect).y + (rect).height))
-
- if (! sc_rect_contains (cci->bg_rect, pt->x + cci->x, pt->y + cci->y)) { continue;}
-
-#undef sc_rect_contains
-
- gegl_buffer_sample (cci->aux_buf, pt->x, pt->y, NULL, aux_c, format, GEGL_SAMPLER_NEAREST);
- /* Sample the BG with the offset */
- gegl_buffer_sample (cci->input_buf, pt->x + cci->x, pt->y + cci->y, NULL, input_c, format, GEGL_SAMPLER_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,
@@ -160,19 +83,7 @@ process (GeglOperation *operation,
const GeglRectangle *result)
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
- ScPreprocessResult *spr = o->prepare;
-
- gfloat *out_raw, *pixel;
- P2tRuvt *uvt_raw;
- gdouble x, y;
-
- GeglRectangle aux_rect = *gegl_operation_source_get_bounding_box (operation, "aux");
- GeglRectangle to_render, mesh_rect;
-
- ScColorComputeInfo cci;
- P2tRImageConfig imcfg;
-
- Babl *format = babl_format("R'G'B'A float");
+ ScCache *spr = o->prepare;
if (spr == NULL)
{
@@ -180,68 +91,7 @@ process (GeglOperation *operation,
return FALSE;
}
- /* The location of the aux will actually be computed with an offset */
- aux_rect.x += o->x;
- aux_rect.y += o->y;
-
- /* 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);
- uvt_raw = g_new (P2tRuvt, 3 * 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.x = o->x;
- cci.y = o->y;
-
- cci.bg_rect = *gegl_operation_source_get_bounding_box (operation, "input");
-
- /* Render as if there is no offset, since the mesh has no offset */
- mesh_rect.x = imcfg.min_x = to_render.x - o->x;
- mesh_rect.y = imcfg.min_y = to_render.y - o->y;
- imcfg.step_x = imcfg.step_y = 1;
- mesh_rect.width = imcfg.x_samples = to_render.width;
- mesh_rect.height = imcfg.y_samples = to_render.height;
- imcfg.cpp = 4;
-
- gegl_buffer_get (spr->uvt, 1.0, &mesh_rect, babl_uvt_format, uvt_raw, GEGL_AUTO_ROWSTRIDE);
- p2tr_mesh_render_scanline2 (uvt_raw, 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_SAMPLER_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_free (uvt_raw);
- g_hash_table_destroy (cci.pt2col);
-
- return TRUE;
+ return sc_render_seamless (input, aux, o->x, o->y, output, result, spr);
}
static void
diff --git a/operations/common/seamless-clone/seamless-clone.c b/operations/common/seamless-clone/seamless-clone.c
index b50eca7..006642a 100644
--- a/operations/common/seamless-clone/seamless-clone.c
+++ b/operations/common/seamless-clone/seamless-clone.c
@@ -35,7 +35,7 @@ gegl_chant_int (max_refine_steps, _("Refinement Steps"), 0, 100000.0, 2000,
#include "poly2tri-c/poly2tri.h"
#include "poly2tri-c/refine/triangulation.h"
#include "poly2tri-c/render/mesh-render.h"
-#include "seamless-clone.h"
+#include "seamless-clone-common.h"
static GeglRectangle
get_required_for_output (GeglOperation *operation,
@@ -44,8 +44,6 @@ get_required_for_output (GeglOperation *operation,
{
GeglRectangle *temp = NULL;
GeglRectangle result;
-
- g_debug ("seamless-clone.c::get_required_for_output");
if (g_strcmp0 (input_pad, "input") || g_strcmp0 (input_pad, "aux"))
temp = gegl_operation_source_get_bounding_box (operation, input_pad);
@@ -67,73 +65,11 @@ prepare (GeglOperation *operation)
{
Babl *format = babl_format ("R'G'B'A float");
- g_debug ("seamless-clone.c::prepare");
-
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;
-} 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);
- // g_print ("%f+",weight);
-
- gegl_buffer_sample (cci->aux_buf, pt->x, pt->y, NULL, aux_c, format, GEGL_SAMPLER_NEAREST);
- gegl_buffer_sample (cci->input_buf, pt->x, pt->y, NULL, input_c, format, GEGL_SAMPLER_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;
- }
-
- // g_print ("=%f\n",weightT);
- 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;
- //g_print ("(%f,%f,%f)",dest[0],dest[1],dest[2]);
-}
-
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
@@ -141,112 +77,14 @@ process (GeglOperation *operation,
GeglBuffer *output,
const GeglRectangle *result)
{
- gfloat *out_raw, *aux_raw;
- gdouble x, y;
-
- GeglRectangle aux_rect = *gegl_operation_source_get_bounding_box (operation, "aux");
- GeglRectangle to_render;
-
- ScOutline *outline;
-
- P2tRTriangulation *mesh;
- GeglRectangle mesh_bounds;
-
- ScMeshSampling *mesh_sampling;
-
- ScColorComputeInfo cci;
- P2tRImageConfig imcfg;
-
- Babl *format = babl_format("R'G'B'A float");
- int max_refine_steps = GEGL_CHANT_PROPERTIES (operation)->max_refine_steps;
-
- GeglBufferIterator *mesh_area_iter;
- int iter_out_index, iter_aux_index;
-
- g_debug ("seamless-clone.c::process");
- printf ("The aux_rect is: ");
- gegl_rectangle_dump (&aux_rect);
-
- /********************************************************************/
- /* Part 1: The preprocessing */
- /********************************************************************/
-
- /* First, find the paste outline */
- g_debug ("Start making outline");
- outline = sc_outline_find_ccw (&aux_rect, aux);
- g_debug ("Finish making outline");
-
- /* Then, Generate the mesh */
- g_debug ("Start making fine mesh with at most %d points", max_refine_steps);
- mesh = sc_make_fine_mesh (outline, &mesh_bounds, max_refine_steps);
- g_debug ("Finish making fine mesh");
-
- /* Finally, Generate the mesh sample list for each point */
- g_debug ("Start computing sampling");
- mesh_sampling = sc_mesh_sampling_compute (outline, mesh);
- g_debug ("Finish computing sampling");
-
- /* If caching of UV is desired, it shold be done here! */
+ gboolean return_val;
+ ScCache *cache;
- /********************************************************************/
- /* Part 2: The rendering */
- /********************************************************************/
-
- /* We only need to render the intersection of the mesh bounds and the
- * desired output */
- gegl_rectangle_intersect (&to_render, result, &mesh_bounds);
-
- /* Render the mesh into it */
- cci.aux_buf = aux;
- cci.input_buf = input;
- cci.sampling = mesh_sampling;
- cci.pt2col = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- /* AUX = PASTE
- * INPUT = BG
- */
- mesh_area_iter = gegl_buffer_iterator_new (output, &to_render, format,
- GEGL_BUFFER_WRITE);
- iter_out_index = 0;
- iter_aux_index = gegl_buffer_iterator_add (mesh_area_iter, aux,
- &to_render, format,
- GEGL_BUFFER_READ);
-
- while (gegl_buffer_iterator_next (mesh_area_iter))
- {
- imcfg.min_x = mesh_area_iter->roi[iter_out_index].x;
- imcfg.min_y = mesh_area_iter->roi[iter_out_index].y;
- imcfg.step_x = imcfg.step_y = 1;
- imcfg.x_samples = mesh_area_iter->roi[iter_out_index].width;
- imcfg.y_samples = mesh_area_iter->roi[iter_out_index].height;
- imcfg.cpp = 4;
-
- out_raw = (gfloat*)mesh_area_iter->data[iter_out_index];
- aux_raw = (gfloat*)mesh_area_iter->data[iter_aux_index];
- p2tr_mesh_render_scanline (mesh, out_raw, &imcfg, sc_point_to_color_func, &cci);
-
- for (y = 0; y < imcfg.y_samples; y++)
- {
- for (x = 0; x < imcfg.x_samples; x++)
- {
- out_raw[0] += aux_raw[0];
- out_raw[1] += aux_raw[1];
- out_raw[2] += aux_raw[2];
- out_raw += 4;
- aux_raw += 4;
- }
- }
- }
-
- g_debug ("Finish aux adding");
+ cache = sc_generate_cache (aux, gegl_operation_source_get_bounding_box (operation, "aux"), GEGL_CHANT_PROPERTIES (operation) -> max_refine_steps);
+ return_val = sc_render_seamless (input, aux, 0, 0, output, result, cache);
+ sc_cache_free (cache);
- /* Free memory, by the order things were allocated! */
- g_hash_table_destroy (cci.pt2col);
- sc_mesh_sampling_free (mesh_sampling);
- p2tr_triangulation_free (mesh);
- sc_outline_free (outline);
-
- return TRUE;
+ return return_val;
}
static void
@@ -264,5 +102,4 @@ gegl_chant_class_init (GeglChantClass *klass)
composer_class->process = process;
}
-
#endif
diff --git a/operations/common/seamless-clone/seamless-clone.h b/operations/common/seamless-clone/seamless-clone.h
index ddb1571..a4f8e0a 100644
--- a/operations/common/seamless-clone/seamless-clone.h
+++ b/operations/common/seamless-clone/seamless-clone.h
@@ -46,7 +46,7 @@ typedef struct {
// g_free (self);
//}
-#define babl_uvt_type (babl_type_new ("uvt", "bits", sizeof (P2tRuvt) * 8, NULL))
-#define babl_uvt_format (babl_format_n (babl_uvt_type, 3))
+#define SC_BABL_UVT_TYPE (babl_type_new ("uvt", "bits", sizeof (P2tRuvt) * 8, NULL))
+#define SC_BABL_UVT_FORMAT (babl_format_n (SC_BABL_UVT_TYPE, 3))
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]