[gegl/soc-2011-seamless-clone: 20/23] Remove code duplication between the seamless-clone operations



commit 472173b6abacdd96f28f579fb5323295ad13e1af
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]