Commit 6e0a1552 authored by Barak Itkin's avatar Barak Itkin
Browse files

Allow points on the boundry of the area not to use a sample list

parent fc18eb3f
......@@ -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,
......@@ -389,6 +394,68 @@ sc_context_render_cache_pt2col_update (ScContext *context,
return TRUE;
}
/**
* 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
......@@ -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);
}
......@@ -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);
}
......
......@@ -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
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment