[gegl/soc-2011-seamless-clone: 43/49] Allow an ScContext object to be efficiently updated to a new input
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-seamless-clone: 43/49] Allow an ScContext object to be efficiently updated to a new input
- Date: Sat, 29 Sep 2012 20:30:29 +0000 (UTC)
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]