[gegl/soc-2011-seamless-clone] Allow an ScContext object to be efficiently updated to a new input



commit 89fa4841134c7476b9127bf1a29e319b078d7796
Author: Barak Itkin <lightningismyname gmail com>
Date:   Wed Sep 26 17:16:53 2012 +0200

    Allow an ScContext object to be efficiently updated to a new input

 .../common/seamless-clone/sc-context-private.h     |    1 -
 operations/common/seamless-clone/sc-context.c      |  119 ++++++++++++++++----
 operations/common/seamless-clone/sc-context.h      |   11 ++-
 operations/common/seamless-clone/sc-outline.c      |   25 ++++
 operations/common/seamless-clone/sc-outline.h      |    7 +-
 5 files changed, 136 insertions(+), 27 deletions(-)
---
diff --git a/operations/common/seamless-clone/sc-context-private.h b/operations/common/seamless-clone/sc-context-private.h
index 41ee52c..7aeaa0c 100644
--- a/operations/common/seamless-clone/sc-context-private.h
+++ b/operations/common/seamless-clone/sc-context-private.h
@@ -30,7 +30,6 @@
 typedef struct
 {
   GHashTable     *pt2col;
-  ScRenderInfo   *info;
   gboolean        is_valid;
 } ScRenderCache;
 
diff --git a/operations/common/seamless-clone/sc-context.c b/operations/common/seamless-clone/sc-context.c
index 32f9b22..23454ea 100644
--- a/operations/common/seamless-clone/sc-context.c
+++ b/operations/common/seamless-clone/sc-context.c
@@ -36,7 +36,11 @@ static P2trMesh*   sc_make_fine_mesh                     (ScOutline           *o
                                                           GeglRectangle       *mesh_bounds,
                                                           int                  max_refine_steps);
 
-static gboolean    sc_context_render_cache_pt2col_update (ScContext           *context);
+static void        sc_context_update_from_outline        (ScContext           *self,
+                                                          ScOutline           *outline);
+
+static gboolean    sc_context_render_cache_pt2col_update (ScContext           *context,
+                                                          ScRenderInfo        *info);
 
 static gboolean    sc_context_sample_point               (ScRenderInfo        *info,
                                                           ScSampleList        *sl,
@@ -61,7 +65,6 @@ sc_context_new (GeglBuffer          *input,
                 ScCreationError     *error)
 {
   ScOutline *outline;
-  guint      outline_length;
   ScContext *self;
 
   outline = sc_context_create_outline (input, roi, threshold, error);
@@ -69,22 +72,45 @@ sc_context_new (GeglBuffer          *input,
   if (outline == NULL)
     return NULL;
 
-  self           = g_slice_new (ScContext);
-  outline_length = sc_outline_length (outline);
-
-  self->outline      = outline;
-  self->mesh         = sc_make_fine_mesh (self->outline,
-                                          &self->mesh_bounds,
-                                          5 * outline_length);
-  self->sampling     = sc_mesh_sampling_compute (self->outline,
-                                                 self->mesh);
+  self               = g_slice_new (ScContext);
+  self->outline      = NULL;
+  self->mesh         = NULL;
+  self->sampling     = NULL;
   self->cache_uvt    = FALSE;
   self->uvt          = NULL;
   self->render_cache = NULL;
 
+  sc_context_update_from_outline (self, outline);
+
   return self;
 }
 
+gboolean
+sc_context_update (ScContext           *self,
+                   GeglBuffer          *input,
+                   const GeglRectangle *roi,
+                   gdouble              threshold,
+                   ScCreationError     *error)
+{
+  ScOutline *outline = sc_context_create_outline (input, roi,
+                                                  threshold, error);
+
+  if (outline == NULL)
+    {
+      return FALSE;
+    }
+  else if (sc_outline_equals (outline, self->outline))
+    {
+      sc_outline_free (outline);
+      return TRUE;
+    }
+  else
+    {
+      sc_context_update_from_outline (self, outline);
+      return TRUE;
+    }
+}
+
 static ScOutline*
 sc_context_create_outline (GeglBuffer          *input,
                            const GeglRectangle *roi,
@@ -125,6 +151,56 @@ sc_context_create_outline (GeglBuffer          *input,
   return outline;
 }
 
+
+static void
+sc_context_update_from_outline (ScContext *self,
+                                ScOutline *outline)
+{
+  guint outline_length;
+
+  if (outline == self->outline)
+    return;
+
+  if (self->render_cache != NULL)
+    {
+      sc_context_render_cache_free (self);
+    }
+
+  if (self->uvt != NULL)
+    {
+      g_object_unref (self->uvt);
+      self->uvt = NULL;
+    }
+
+  if (self->sampling != NULL)
+    {
+      sc_mesh_sampling_free (self->sampling);
+      self->sampling = NULL;
+    }
+
+  if (self->mesh != NULL)
+    {
+      p2tr_mesh_unref (self->mesh);
+      self->mesh = NULL;
+    }
+
+  if (self->outline != NULL)
+    {
+      sc_outline_free (self->outline);
+      self->outline = NULL;
+    }
+
+  outline_length = sc_outline_length (outline);
+
+  self->outline  = outline;
+  self->mesh     = sc_make_fine_mesh (self->outline,
+                                      &self->mesh_bounds,
+                                      5 * outline_length);
+  self->sampling = sc_mesh_sampling_compute (self->outline,
+                                             self->mesh);
+}
+
+
 /**
  * sc_make_fine_mesh:
  * @outline: An ScOutline object describing the PSLG of the mesh
@@ -202,9 +278,7 @@ sc_context_prepare_render (ScContext    *context,
 
   context->render_cache->is_valid = FALSE;
 
-  context->render_cache->info = info;
-
-  if (! sc_context_render_cache_pt2col_update (context))
+  if (! sc_context_render_cache_pt2col_update (context, info))
     return FALSE;
 
   if (context->cache_uvt && context->uvt == NULL)
@@ -224,7 +298,8 @@ sc_context_prepare_render (ScContext    *context,
  * RENDERING PROCESS!
  */
 static gboolean
-sc_context_render_cache_pt2col_update (ScContext *context)
+sc_context_render_cache_pt2col_update (ScContext    *context,
+                                       ScRenderInfo *info)
 {
   GHashTableIter iter;
 
@@ -280,8 +355,7 @@ sc_context_render_cache_pt2col_update (ScContext *context)
        * after allocating/reffing but before inserting, we would have a
        * memory leak!
        */
-      if (! sc_context_sample_point (context->render_cache->info, sl,
-                                     pt, color_current))
+      if (! sc_context_sample_point (info, sl, pt, color_current))
         {
           return FALSE;
         }
@@ -454,7 +528,7 @@ sc_compute_uvt_cache (P2trMesh            *mesh,
 
 void
 sc_context_set_uvt_cache (ScContext *context,
-                          gboolean   enabled)
+                          gboolean  enabled)
 {
   context->cache_uvt = enabled;
   if (! enabled && context->uvt != NULL)
@@ -466,6 +540,7 @@ sc_context_set_uvt_cache (ScContext *context,
 
 gboolean
 sc_context_render (ScContext           *context,
+                   ScRenderInfo        *info,
                    const GeglRectangle *part_rect,
                    GeglBuffer          *part)
 {
@@ -499,7 +574,7 @@ sc_context_render (ScContext           *context,
       return TRUE;
     }
 
-  if (! gegl_rectangle_contains (&context->render_cache->info->fg_rect,
+  if (! gegl_rectangle_contains (&info->fg_rect,
                                  &context->mesh_bounds))
     {
       g_warning ("The mesh from the preprocessing is not inside the "
@@ -507,8 +582,8 @@ sc_context_render (ScContext           *context,
       return FALSE;
     }
 
-  xoff = context->render_cache->info->xoff;
-  yoff = context->render_cache->info->yoff;
+  xoff = info->xoff;
+  yoff = info->yoff;
 
   /* The real rectangle of the foreground that we should render is
    * defined by the bounds of the mesh plus the given offset */
@@ -559,7 +634,7 @@ sc_context_render (ScContext           *context,
     }
 
   fg_index  = gegl_buffer_iterator_add (iter,
-                                        context->render_cache->info->fg,
+                                        info->fg,
                                         &to_render_fg,
                                         0,
                                         format,
diff --git a/operations/common/seamless-clone/sc-context.h b/operations/common/seamless-clone/sc-context.h
index c5f915c..e373982 100644
--- a/operations/common/seamless-clone/sc-context.h
+++ b/operations/common/seamless-clone/sc-context.h
@@ -64,6 +64,12 @@ ScContext* sc_context_new            (GeglBuffer          *input,
                                       gdouble              threshold,
                                       ScCreationError     *error);
 
+gboolean   sc_context_update         (ScContext           *self,
+                                      GeglBuffer          *input,
+                                      const GeglRectangle *roi,
+                                      gdouble              threshold,
+                                      ScCreationError     *error);
+
 /**
  * Do the necessary caching so that rendering can happen. This function
  * is not thread-safe, and must be called before each call to the
@@ -73,8 +79,8 @@ ScContext* sc_context_new            (GeglBuffer          *input,
  * BEHAVIOUR IS THAT THE FOREGROUND DOES NOT OVERLAP ENOUGH THE
  * BACKGROUND!
  */
-gboolean       sc_context_prepare_render (ScContext       *context,
-                                          ScRenderInfo    *info);
+gboolean   sc_context_prepare_render (ScContext           *context,
+                                      ScRenderInfo        *info);
 
 /**
  * Specifies whether the triangle containing each pixel, along with the
@@ -92,6 +98,7 @@ void       sc_context_set_uvt_cache  (ScContext           *context,
  * the prepare function.
  */
 gboolean   sc_context_render         (ScContext           *context,
+                                      ScRenderInfo        *info,
                                       const GeglRectangle *part_rect,
                                       GeglBuffer          *part);
 
diff --git a/operations/common/seamless-clone/sc-outline.c b/operations/common/seamless-clone/sc-outline.c
index f016897..7f72e8b 100644
--- a/operations/common/seamless-clone/sc-outline.c
+++ b/operations/common/seamless-clone/sc-outline.c
@@ -358,6 +358,31 @@ sc_outline_length (ScOutline *self)
   return ((GPtrArray*) self)->len;
 }
 
+gboolean
+sc_outline_equals (ScOutline *a,
+                   ScOutline *b)
+{
+  if (a == b) /* Includes the case were both are NULL */
+    return TRUE;
+  else if ((a == NULL) != (b == NULL))
+    return FALSE;
+  else if (sc_outline_length (a) != sc_outline_length (b))
+    return FALSE;
+  else
+    {
+      guint n = sc_outline_length (a);
+      guint i;
+      for (i = 0; i < n; i++)
+        {
+          const ScPoint *pA = (ScPoint*) g_ptr_array_index (a, i);
+          const ScPoint *pB = (ScPoint*) g_ptr_array_index (b, i);
+          if (sc_point_cmp (&pA, &pB) != 0)
+            return FALSE;
+        }
+      return TRUE;
+    }
+}
+
 void
 sc_outline_free (ScOutline *self)
 {
diff --git a/operations/common/seamless-clone/sc-outline.h b/operations/common/seamless-clone/sc-outline.h
index 4da83ad..d49c812 100644
--- a/operations/common/seamless-clone/sc-outline.h
+++ b/operations/common/seamless-clone/sc-outline.h
@@ -114,8 +114,11 @@ gboolean   sc_outline_check_if_single (const GeglRectangle *search_area,
                                        GeglBuffer          *buffer,
                                        ScOutline           *existing);
 
-guint      sc_outline_length          (ScOutline *self);
+guint      sc_outline_length          (ScOutline           *self);
 
-void       sc_outline_free            (ScOutline *self);
+gboolean   sc_outline_equals          (ScOutline           *a,
+                                       ScOutline           *b);
+
+void       sc_outline_free            (ScOutline           *self);
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]