[gegl/soc-2011-seamless-clone] Allow points on the boundry of the area not to use a sample list
- From: Barak Itkin <barakitkin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-seamless-clone] Allow points on the boundry of the area not to use a sample list
- Date: Sat, 29 Sep 2012 20:04:58 +0000 (UTC)
commit 9382d3a809a5259d5e1928e3313086e46fb075e1
Author: Barak Itkin <lightningismyname gmail com>
Date: Sat Sep 29 03:49:09 2012 +0200
Allow points on the boundry of the area not to use a sample list
operations/common/seamless-clone/sc-context.c | 164 +++++++++++++++---------
operations/common/seamless-clone/sc-sample.c | 44 ++++++--
operations/common/seamless-clone/sc-sample.h | 3 +
3 files changed, 140 insertions(+), 71 deletions(-)
---
diff --git a/operations/common/seamless-clone/sc-context.c b/operations/common/seamless-clone/sc-context.c
index 941e1c2..fcbea7e 100644
--- a/operations/common/seamless-clone/sc-context.c
+++ b/operations/common/seamless-clone/sc-context.c
@@ -42,6 +42,11 @@ static void sc_context_update_from_outline (ScContext *s
static gboolean sc_context_render_cache_pt2col_update (ScContext *context,
ScRenderInfo *info);
+static gboolean sc_context_sample_color_difference (ScRenderInfo *info,
+ gdouble x,
+ gdouble y,
+ ScColor *dest);
+
static gboolean sc_context_sample_point (ScRenderInfo *info,
ScSampleList *sl,
P2trPoint *point,
@@ -390,6 +395,68 @@ sc_context_render_cache_pt2col_update (ScContext *context,
}
/**
+ * Compute the color difference between the foreground and background
+ * at a given point. This function returns FALSE if the difference can
+ * not be computed since the background buffer does not contain the
+ * point. Otherwise, the function returns TRUE.
+ * THIS FUNCTION USES SC_COLORA_CHANNEL_COUNT CHANNELS! (WITH ALPHA!)
+ */
+static gboolean
+sc_context_sample_color_difference (ScRenderInfo *info,
+ gdouble x,
+ gdouble y,
+ ScColor *dest)
+{
+ const Babl *format = babl_format (SC_COLOR_BABL_NAME);
+
+ ScColor fg_c[SC_COLORA_CHANNEL_COUNT];
+ ScColor bg_c[SC_COLORA_CHANNEL_COUNT];
+
+ /* 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.
+ *
+ * The outline point obviously must lie inside the foreground, so
+ * we don't have anything to worry about here.
+ *
+ * The only thing we should notice, is to use the right
+ * coordinates: The original outline point is on (pt->x,pt->y) in
+ * terms of mesh coordinates. But, since we are translating, its
+ * location in background coordinates is the following:
+ * (pt->x + info->x, pt->y + info->y).
+ */
+#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 (info->bg_rect,
+ x + info->xoff,
+ y + info->yoff))
+ {
+ return FALSE;
+ }
+
+#undef sc_rect_contains
+
+ gegl_buffer_sample (info->fg,
+ x, y,
+ NULL, fg_c, format,
+ GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
+
+ /* Sample the BG with the offset */
+ gegl_buffer_sample (info->bg,
+ x + info->xoff, y + info->yoff,
+ NULL, bg_c, format,
+ GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
+
+#define sc_color_expr(I) dest[I] = (bg_c[I] - fg_c[I])
+ sc_color_process();
+#undef sc_color_expr
+ dest[SC_COLOR_ALPHA_INDEX] = 1;
+ return TRUE;
+}
+
+/**
* Compute the color assigned to a given point in the color difference
* mesh. If the color can not be computed since all the sample points
* assigned to this mesh point are outside the background, this function
@@ -402,75 +469,48 @@ sc_context_sample_point (ScRenderInfo *info,
ScSampleList *sl,
P2trPoint *point,
ScColor *dest)
-{
- gint i;
- gdouble weightT = 0;
- guint N = sl->points->len;
-
- const Babl *format = babl_format (SC_COLOR_BABL_NAME);
-
- gfloat fg_c[SC_COLORA_CHANNEL_COUNT];
- gfloat bg_c[SC_COLORA_CHANNEL_COUNT];
-
- /* We don't need an alpha for this one */
- gfloat dest_c[SC_COLOR_CHANNEL_COUNT] = { 0 };
-
- for (i = 0; i < N; i++)
+{
+ /* If this is a direct sample, we can easily finish */
+ if (sl->direct_sample)
+ {
+ return sc_context_sample_color_difference (info, point->c.x, point->c.y, dest);
+ }
+ else
{
- ScPoint *pt = g_ptr_array_index (sl->points, i);
- gdouble weight = g_array_index (sl->weights, gdouble, i);
+ gdouble weightT = 0;
+ /* Don't be tempted to initialize earlier - sl->points may be NULL if
+ * this is a direct sample list! */
+ guint N = sl->points->len;
- /* 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.
- *
- * The outline point obviously must lie inside the foreground, so
- * we don't have anything to worry about here.
- *
- * The only thing we should notice, is to use the right
- * coordinates: The original outline point is on (pt->x,pt->y) in
- * terms of mesh coordinates. But, since we are translating, its
- * location in background coordinates is the following:
- * (pt->x + info->x, pt->y + info->y).
- */
-#define sc_rect_contains(rect,x0,y0) \
- (((x0) >= (rect).x) && ((x0) < (rect).x + (rect).width) \
- && ((y0) >= (rect).y) && ((y0) < (rect).y + (rect).height))
+ gint i;
+ /* We need an alpha for this one */
+ ScColor dest_c[SC_COLORA_CHANNEL_COUNT] = { 0 };
- if (! sc_rect_contains (info->bg_rect,
- pt->x + info->xoff,
- pt->y + info->yoff))
+ for (i = 0; i < N; i++)
{
- continue;
- }
-
-#undef sc_rect_contains
+ ScPoint *pt = g_ptr_array_index (sl->points, i);
+ gdouble weight = g_array_index (sl->weights, gdouble, i);
+ ScColor raw_color[SC_COLORA_CHANNEL_COUNT];
- gegl_buffer_sample (info->fg,
- pt->x, pt->y,
- NULL, fg_c, format,
- GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
+ if (! sc_context_sample_color_difference (info, pt->x, pt->y, raw_color))
+ continue;
- /* Sample the BG with the offset */
- gegl_buffer_sample (info->bg,
- pt->x + info->xoff, pt->y + info->yoff,
- NULL, bg_c, format,
- GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
-
-#define sc_color_expr(I) dest_c[I] += weight * (bg_c[I] - fg_c[I])
- sc_color_process();
+#define sc_color_expr(I) dest_c[I] += weight * raw_color[I]
+ sc_color_process();
#undef sc_color_expr
- weightT += weight;
- }
+ weightT += weight;
+ }
- if (weightT == 0)
- return FALSE;
+ if (weightT == 0)
+ return FALSE;
#define sc_color_expr(I) dest[I] = dest_c[I] / weightT
- sc_color_process();
+ sc_color_process();
#undef sc_color_expr
- dest[SC_COLOR_ALPHA_INDEX] = 1;
- return TRUE;
+ dest[SC_COLOR_ALPHA_INDEX] = 1;
+
+ return TRUE;
+ }
}
static void
@@ -618,7 +658,7 @@ sc_context_render (ScContext *context,
GEGL_BUFFER_WRITE,
GEGL_ABYSS_NONE);
out_index = 0;
-
+
gegl_rectangle_set (&to_render_fg,
to_render.x - xoff, to_render.y - yoff,
to_render.width, to_render.height);
@@ -652,7 +692,7 @@ sc_context_render (ScContext *context,
float *out_raw, *fg_raw;
P2trUVT *uvt_raw;
int x, y;
-
+
imcfg.min_x = iter->roi[fg_index].x;
imcfg.min_y = iter->roi[fg_index].y;
imcfg.step_x = imcfg.step_y = 1;
@@ -697,7 +737,7 @@ sc_context_render (ScContext *context,
}
}
}
-
+
return TRUE;
}
@@ -741,6 +781,6 @@ sc_context_free (ScContext *context)
sc_outline_free (context->outline);
g_slice_free (ScContext, context);
-
+
}
diff --git a/operations/common/seamless-clone/sc-sample.c b/operations/common/seamless-clone/sc-sample.c
index 585dff1..800d018 100644
--- a/operations/common/seamless-clone/sc-sample.c
+++ b/operations/common/seamless-clone/sc-sample.c
@@ -109,7 +109,12 @@ sc_compute_sample_list_weights (gdouble Px,
norms[i] = norm1;
- /* Did the point match one of the outline points? */
+ /* Did the point match one of the outline points? If so, convert
+ * the sample list to be made only of that outline point.
+ * This shouldn't happen since we give a direct sample list to
+ * boundry points, but this is a backup and also in case that due
+ * to small distances the norm came out zero
+ */
if (norm1 == 0)
{
gdouble temp = 1;
@@ -158,6 +163,7 @@ sc_sample_list_compute (ScOutline *outline,
GPtrArray *real = (GPtrArray*) outline;
gint i;
+ sl->direct_sample = FALSE;
sl->points = g_ptr_array_new ();
sl->weights = g_array_new (FALSE, TRUE, sizeof (gdouble));
@@ -168,13 +174,10 @@ sc_sample_list_compute (ScOutline *outline,
}
else
{
- gdouble div = real->len / ((gdouble) SC_SAMPLE_BASE_POINT_COUNT);
- gint index1, index2;
-
for (i = 0; i < SC_SAMPLE_BASE_POINT_COUNT; i++)
{
- index1 = (gint) (i * div);
- index2 = (gint) ((i + 1) * div);
+ gint index1 = i * real->len / SC_SAMPLE_BASE_POINT_COUNT;
+ gint index2 = (i + 1) * real->len / SC_SAMPLE_BASE_POINT_COUNT;
sc_compute_sample_list_part (outline, index1, index2, Px, Py, sl, 0);
}
@@ -185,11 +188,30 @@ sc_sample_list_compute (ScOutline *outline,
return sl;
}
+ScSampleList*
+sc_sample_list_direct (void)
+{
+ ScSampleList *sl = g_slice_new (ScSampleList);
+ sl->direct_sample = TRUE;
+ sl->points = NULL;
+ sl->weights = NULL;
+ sl->total_weight = 0;
+ return sl;
+}
+
void
sc_sample_list_free (ScSampleList *self)
{
- g_ptr_array_free (self->points, TRUE);
- g_array_free (self->weights, TRUE);
+ if (! self->direct_sample)
+ {
+ g_ptr_array_free (self->points, TRUE);
+ g_array_free (self->weights, TRUE);
+ }
+ else
+ {
+ g_assert (self->points == NULL);
+ g_assert (self->weights == NULL);
+ }
g_slice_free (ScSampleList, self);
}
@@ -204,7 +226,11 @@ sc_mesh_sampling_compute (ScOutline *outline,
p2tr_hash_set_iter_init (&iter, mesh->points);
while (p2tr_hash_set_iter_next (&iter, (gpointer*) &pt))
{
- ScSampleList *sl = sc_sample_list_compute (outline, pt->c.x, pt->c.y);
+ ScSampleList *sl;
+ if (p2tr_point_is_fully_in_domain (pt))
+ sl = sc_sample_list_compute (outline, pt->c.x, pt->c.y);
+ else
+ sl = sc_sample_list_direct ();
g_hash_table_insert (pt2sample, pt, sl);
}
diff --git a/operations/common/seamless-clone/sc-sample.h b/operations/common/seamless-clone/sc-sample.h
index e42e10d..0bb4fd6 100644
--- a/operations/common/seamless-clone/sc-sample.h
+++ b/operations/common/seamless-clone/sc-sample.h
@@ -26,6 +26,8 @@
#include "sc-outline.h"
typedef struct {
+ /** Should the point behind this list be sampled directly? */
+ gboolean direct_sample;
/** An array of ScPoint* (pointers) of the points to sample */
GPtrArray *points;
/** An array of weights to assign to the samples from the points */
@@ -45,6 +47,7 @@ ScSampleList* sc_sample_list_compute (ScOutline *outline,
gdouble x,
gdouble y);
+ScSampleList* sc_sample_list_direct (void);
/**
* Free an ScSampleList object created by sc_sample_list_compute
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]