Commit 4a45593d authored by Barak Itkin's avatar Barak Itkin
Browse files

Respect the threshold parameter when finding the outline

parent 6e0a1552
......@@ -77,4 +77,11 @@ typedef struct {
gboolean render_bg;
} ScRenderInfo;
#define sc_point_in_rectangle(px, py, rect) \
( ((px) >= (rect)->x) \
&& ((py) >= (rect)->y) \
&& ((px) < (rect)->x + (rect)->width) \
&& ((py) < (rect)->y + (rect)->height) \
)
#endif
......@@ -123,7 +123,7 @@ sc_context_create_outline (GeglBuffer *input,
ScCreationError *error)
{
gboolean ignored_islands = FALSE;
ScOutline *outline = sc_outline_find (roi, input, &ignored_islands);
ScOutline *outline = sc_outline_find (roi, input, threshold, &ignored_islands);
guint length = sc_outline_length (outline);
*error = SC_CREATION_ERROR_NONE;
......@@ -144,7 +144,7 @@ sc_context_create_outline (GeglBuffer *input,
*error = SC_CREATION_ERROR_TOO_SMALL;
}
else if (ignored_islands ||
! sc_outline_check_if_single (roi, input, outline))
! sc_outline_check_if_single (roi, input, threshold, outline))
{
*error = SC_CREATION_ERROR_HOLED_OR_SPLIT;
}
......@@ -425,19 +425,13 @@ sc_context_sample_color_difference (ScRenderInfo *info,
* 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))
if (! sc_point_in_rectangle (x + info->xoff,
y + info->yoff,
&info->bg_rect))
{
return FALSE;
}
#undef sc_rect_contains
gegl_buffer_sample (info->fg,
x, y,
NULL, fg_c, format,
......
......@@ -22,7 +22,7 @@
*
* Terminology:
*
* Opaque - A pixel with alpha of at least 0.5
* Opaque - A pixel with alpha of at least a given threshold
* Island - An opaque pixel with 8 non-opaque neighbors
* Edge - An opaque pixel with at least 1 (out of 8) non-opaque
* neighbors
......@@ -41,6 +41,7 @@
#include <gegl.h>
#include "sc-outline.h"
#include "sc-common.h"
static inline void
sc_point_copy_to (const ScPoint *src,
......@@ -76,37 +77,22 @@ sc_point_eq (const ScPoint *pt1,
return pt1->x == pt2->x && pt1->y == pt2->y;
}
static inline gboolean
in_range (gint val,
gint min,
gint max)
{
return (min <= val) && (val <= max);
}
static inline gboolean
in_rectangle (const GeglRectangle *rect,
const ScPoint *pt)
{
return in_range (pt->x, rect->x, rect->x + rect->width - 1)
&& in_range (pt->y, rect->y, rect->y + rect->height - 1);
}
static inline gboolean
is_opaque (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
{
gfloat col[4] = {0, 0, 0, 0};
ScColor col[SC_COLORA_CHANNEL_COUNT];
if (! in_rectangle (search_area, pt))
if (! sc_point_in_rectangle (pt->x, pt->y, search_area))
return FALSE;
gegl_buffer_sample (buffer, pt->x, pt->y, NULL, col, format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
return col[3] >= 0.5f;
return col[SC_COLOR_ALPHA_INDEX] >= threshold;
}
/* This function assumes the pixel is opaque! */
......@@ -114,13 +100,14 @@ static inline gboolean
is_opaque_island (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
{
gint i;
ScPoint temp;
for (i = 0; i < 8; ++i)
if (is_opaque (search_area, buffer, format, sc_point_move (pt, i, &temp)))
if (is_opaque (search_area, buffer, format, threshold, sc_point_move (pt, i, &temp)))
return FALSE;
return TRUE;
......@@ -132,16 +119,17 @@ static inline gboolean
is_valid_edge (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *pt)
{
gint i;
ScPoint temp;
if (! is_opaque (search_area, buffer, format, pt))
if (! is_opaque (search_area, buffer, format, threshold, pt))
return FALSE;
for (i = 0; i < 8; ++i)
if (is_opaque (search_area, buffer, format, sc_point_move (pt, i, &temp)))
for (i = 0; i < SC_DIRECTION_COUNT; ++i)
if (is_opaque (search_area, buffer, format, threshold, sc_point_move (pt, i, &temp)))
return FALSE;
return TRUE;
......@@ -166,6 +154,7 @@ static inline ScDirection
walk_cw (const GeglRectangle *search_area,
GeglBuffer *buffer,
const Babl *format,
gdouble threshold,
const ScPoint *cur_pt,
ScDirection dir_from_prev,
ScPoint *next_pt)
......@@ -175,7 +164,7 @@ walk_cw (const GeglRectangle *search_area,
sc_point_move (cur_pt, dir_to_next, next_pt);
while (! is_opaque (search_area, buffer, format, next_pt))
while (! is_opaque (search_area, buffer, format, threshold, next_pt))
{
dir_to_next = SC_DIRECTION_CW (dir_to_next);
sc_point_move (cur_pt, dir_to_next, next_pt);
......@@ -194,6 +183,7 @@ walk_cw (const GeglRectangle *search_area,
ScOutline*
sc_outline_find (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
gboolean *ignored_islands)
{
const Babl *format = babl_format("RGBA float");
......@@ -209,9 +199,9 @@ sc_outline_find (const GeglRectangle *search_area,
for (current.y = search_area->y; current.y < row_max; ++current.y)
{
for (current.x = search_area->x; current.x < col_max; ++current.x)
if (is_opaque (search_area, buffer, format, &current))
if (is_opaque (search_area, buffer, format, threshold, &current))
{
if (is_opaque_island (search_area, buffer, format, &current))
if (is_opaque_island (search_area, buffer, format, threshold, &current))
{
if (ignored_islands)
*ignored_islands = TRUE;
......@@ -232,16 +222,16 @@ sc_outline_find (const GeglRectangle *search_area,
current.outside_normal = SC_DIRECTION_N;
g_ptr_array_add (result, first = sc_point_copy (&current));
to_next = walk_cw (search_area, buffer, format, &current,
SC_DIRECTION_E, &next);
to_next = walk_cw (search_area, buffer, format, threshold,
&current, SC_DIRECTION_E, &next);
while (! sc_point_eq (&next, first))
{
next.outside_normal = SC_DIRECTION_CW(SC_DIRECTION_CW(to_next));
g_ptr_array_add (result, sc_point_copy (&next));
sc_point_copy_to (&next, &current);
to_next = walk_cw (search_area, buffer, format, &current,
to_next, &next);
to_next = walk_cw (search_area, buffer, format, threshold,
&current, to_next, &next);
}
}
......@@ -292,6 +282,7 @@ sc_point_cmp (const ScPoint **pt1,
gboolean
sc_outline_check_if_single (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
ScOutline *existing)
{
const Babl *format = babl_format("RGBA float");
......@@ -319,7 +310,7 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
{
gboolean hit, opaque;
opaque = is_opaque (search_area, buffer, format, &current);
opaque = is_opaque (search_area, buffer, format, threshold, &current);
hit = sc_point_eq (&current, sorted_p);
if (hit && ! inside)
......@@ -331,7 +322,7 @@ sc_outline_check_if_single (const GeglRectangle *search_area,
}
if (inside != opaque
&& ! (opaque && is_opaque_island (search_area, buffer, format, &current)))
&& ! (opaque && is_opaque_island (search_area, buffer, format, threshold, &current)))
{
not_single = FALSE;
break;
......
......@@ -39,19 +39,20 @@
* </pre>
*/
typedef enum {
SC_DIRECTION_N = 0,
SC_DIRECTION_NE = 1,
SC_DIRECTION_E = 2,
SC_DIRECTION_SE = 3,
SC_DIRECTION_S = 4,
SC_DIRECTION_SW = 5,
SC_DIRECTION_W = 6,
SC_DIRECTION_NW = 7
SC_DIRECTION_N = 0,
SC_DIRECTION_NE = 1,
SC_DIRECTION_E = 2,
SC_DIRECTION_SE = 3,
SC_DIRECTION_S = 4,
SC_DIRECTION_SW = 5,
SC_DIRECTION_W = 6,
SC_DIRECTION_NW = 7,
SC_DIRECTION_COUNT = 8
} ScDirection;
#define SC_DIRECTION_CW(d) (((d)+1)%8)
#define SC_DIRECTION_CCW(d) (((d)+7)%8)
#define SC_DIRECTION_OPPOSITE(d) (((d)+4)%8)
#define SC_DIRECTION_CW(d) (((d) + 1) % 8)
#define SC_DIRECTION_CCW(d) (((d) + 7) % 8)
#define SC_DIRECTION_OPPOSITE(d) (((d) + 4) % 8)
#define SC_DIRECTION_IS_NORTH(d) ( \
((d) == SC_DIRECTION_N) || \
......@@ -108,10 +109,12 @@ typedef GPtrArray ScOutline;
ScOutline* sc_outline_find (const GeglRectangle *rect,
GeglBuffer *pixels,
gdouble threshold,
gboolean *ignored_islands);
gboolean sc_outline_check_if_single (const GeglRectangle *search_area,
GeglBuffer *buffer,
gdouble threshold,
ScOutline *existing);
guint sc_outline_length (ScOutline *self);
......
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