[gegl/soc-2011-seamless-clone: 49/49] Respect the threshold parameter when finding the outline



commit 4a45593db6e53cec42319529693a8ec1985a3393
Author: Barak Itkin <lightningismyname gmail com>
Date:   Sat Sep 29 19:44:26 2012 +0200

    Respect the threshold parameter when finding the outline

 operations/common/seamless-clone/sc-common.h  |    7 +++
 operations/common/seamless-clone/sc-context.c |   16 ++-----
 operations/common/seamless-clone/sc-outline.c |   57 ++++++++++--------------
 operations/common/seamless-clone/sc-outline.h |   25 ++++++-----
 4 files changed, 50 insertions(+), 55 deletions(-)
---
diff --git a/operations/common/seamless-clone/sc-common.h b/operations/common/seamless-clone/sc-common.h
index 604f213..12f9b86 100644
--- a/operations/common/seamless-clone/sc-common.h
+++ b/operations/common/seamless-clone/sc-common.h
@@ -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
diff --git a/operations/common/seamless-clone/sc-context.c b/operations/common/seamless-clone/sc-context.c
index fcbea7e..83ed022 100644
--- a/operations/common/seamless-clone/sc-context.c
+++ b/operations/common/seamless-clone/sc-context.c
@@ -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,
diff --git a/operations/common/seamless-clone/sc-outline.c b/operations/common/seamless-clone/sc-outline.c
index 7f72e8b..0c56908 100644
--- a/operations/common/seamless-clone/sc-outline.c
+++ b/operations/common/seamless-clone/sc-outline.c
@@ -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,
@@ -77,36 +78,21 @@ sc_point_eq (const ScPoint *pt1,
 }
 
 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;
diff --git a/operations/common/seamless-clone/sc-outline.h b/operations/common/seamless-clone/sc-outline.h
index d49c812..4636cda 100644
--- a/operations/common/seamless-clone/sc-outline.h
+++ b/operations/common/seamless-clone/sc-outline.h
@@ -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);



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