[gimp/goat-invasion] app: change GimpBoundary to find the boundary a float component



commit ec94c209458a1857a494019dc89e42a9c859a36e
Author: Michael Natterer <mitch gimp org>
Date:   Sat Apr 21 20:10:45 2012 +0200

    app: change GimpBoundary to find the boundary a float component
    
    Require passing in a Babl format that will extract the float component
    the algorithm should run on.

 app/core/gimpboundary.c           |  155 ++++++++++++++++++-------------------
 app/core/gimpboundary.h           |    5 +-
 app/core/gimpbrush-boundary.c     |    3 +-
 app/core/gimpchannel.c            |    2 +
 app/core/gimplayer-floating-sel.c |    1 +
 app/gegl/gimp-gegl.c              |    6 ++
 app/tools/gimpregionselecttool.c  |    1 +
 7 files changed, 92 insertions(+), 81 deletions(-)
---
diff --git a/app/core/gimpboundary.c b/app/core/gimpboundary.c
index 0463778..ff370a8 100644
--- a/app/core/gimpboundary.c
+++ b/app/core/gimpboundary.c
@@ -56,71 +56,71 @@ struct _GimpBoundary
 /*  local function prototypes  */
 
 static GimpBoundary * gimp_boundary_new        (const GeglRectangle *region);
-static GimpBoundSeg * gimp_boundary_free       (GimpBoundary    *boundary,
-                                                gboolean         free_segs);
+static GimpBoundSeg * gimp_boundary_free       (GimpBoundary        *boundary,
+                                                gboolean             free_segs);
 
 static void           gimp_boundary_add_seg    (GimpBoundary        *bounrady,
-                                                gint             x1,
-                                                gint             y1,
-                                                gint             x2,
-                                                gint             y2,
-                                                gboolean         open);
-
-static void           find_empty_segs     (const GeglRectangle *region,
-                                           const guchar        *line_data,
-                                           gint                 bpp,
-                                           gint                 scanline,
-                                           gint                 empty_segs[],
-                                           gint                 max_empty,
-                                           gint                *num_empty,
-                                           GimpBoundaryType     type,
-                                           gint                 x1,
-                                           gint                 y1,
-                                           gint                 x2,
-                                           gint                 y2,
-                                           guchar               threshold);
-static void           process_horiz_seg   (GimpBoundary        *boundary,
-                                           gint                 x1,
-                                           gint                 y1,
-                                           gint                 x2,
-                                           gint                 y2,
-                                           gboolean             open);
-static void           make_horiz_segs     (GimpBoundary        *boundary,
-                                           gint                 start,
-                                           gint                 end,
-                                           gint                 scanline,
-                                           gint                 empty[],
-                                           gint                 num_empty,
-                                           gint                 top);
-static GimpBoundary * generate_boundary   (GeglBuffer          *buffer,
-                                           const GeglRectangle *region,
-                                           GimpBoundaryType     type,
-                                           gint                 x1,
-                                           gint                 y1,
-                                           gint                 x2,
-                                           gint                 y2,
-                                           guchar               threshold);
-
-static gint       cmp_segptr_xy1_addr (const GimpBoundSeg **seg_ptr_a,
-                                       const GimpBoundSeg **seg_ptr_b);
-static gint       cmp_segptr_xy2_addr (const GimpBoundSeg **seg_ptr_a,
-                                       const GimpBoundSeg **seg_ptr_b);
-
-static gint       cmp_segptr_xy1      (const GimpBoundSeg **seg_ptr_a,
-                                       const GimpBoundSeg **seg_ptr_b);
-static gint       cmp_segptr_xy2      (const GimpBoundSeg **seg_ptr_a,
-                                       const GimpBoundSeg **seg_ptr_b);
+                                                gint                 x1,
+                                                gint                 y1,
+                                                gint                 x2,
+                                                gint                 y2,
+                                                gboolean             open);
+
+static void           find_empty_segs          (const GeglRectangle *region,
+                                                const gfloat        *line_data,
+                                                gint                 scanline,
+                                                gint                 empty_segs[],
+                                                gint                 max_empty,
+                                                gint                *num_empty,
+                                                GimpBoundaryType     type,
+                                                gint                 x1,
+                                                gint                 y1,
+                                                gint                 x2,
+                                                gint                 y2,
+                                                gfloat               threshold);
+static void           process_horiz_seg        (GimpBoundary        *boundary,
+                                                gint                 x1,
+                                                gint                 y1,
+                                                gint                 x2,
+                                                gint                 y2,
+                                                gboolean             open);
+static void           make_horiz_segs          (GimpBoundary        *boundary,
+                                                gint                 start,
+                                                gint                 end,
+                                                gint                 scanline,
+                                                gint                 empty[],
+                                                gint                 num_empty,
+                                                gint                 top);
+static GimpBoundary * generate_boundary        (GeglBuffer          *buffer,
+                                                const GeglRectangle *region,
+                                                const Babl          *format,
+                                                GimpBoundaryType     type,
+                                                gint                 x1,
+                                                gint                 y1,
+                                                gint                 x2,
+                                                gint                 y2,
+                                                gfloat               threshold);
+
+static gint       cmp_segptr_xy1_addr     (const GimpBoundSeg **seg_ptr_a,
+                                           const GimpBoundSeg **seg_ptr_b);
+static gint       cmp_segptr_xy2_addr     (const GimpBoundSeg **seg_ptr_a,
+                                           const GimpBoundSeg **seg_ptr_b);
+
+static gint       cmp_segptr_xy1          (const GimpBoundSeg **seg_ptr_a,
+                                           const GimpBoundSeg **seg_ptr_b);
+static gint       cmp_segptr_xy2          (const GimpBoundSeg **seg_ptr_a,
+                                           const GimpBoundSeg **seg_ptr_b);
 
 static const GimpBoundSeg * find_segment  (const GimpBoundSeg **segs_by_xy1,
                                            const GimpBoundSeg **segs_by_xy2,
-                                           gint             num_segs,
-                                           gint             x,
-                                           gint             y);
+                                           gint                 num_segs,
+                                           gint                 x,
+                                           gint                 y);
 
 static const GimpBoundSeg * find_segment_with_func (const GimpBoundSeg **segs,
-                                                    gint             num_segs,
+                                                    gint                 num_segs,
                                                     const GimpBoundSeg  *search_seg,
-                                                    GCompareFunc     cmp_func);
+                                                    GCompareFunc         cmp_func);
 
 static void       simplify_subdivide  (const GimpBoundSeg  *segs,
                                        gint                 start_idx,
@@ -133,6 +133,7 @@ static void       simplify_subdivide  (const GimpBoundSeg  *segs,
 /**
  * gimp_boundary_find:
  * @maskPR:    any PixelRegion
+ * @format:    a #Babl float format representing the component to analyze
  * @type:      type of bounds
  * @x1:        left side of bounds
  * @y1:        top side of bounds
@@ -154,12 +155,13 @@ static void       simplify_subdivide  (const GimpBoundSeg  *segs,
 GimpBoundSeg *
 gimp_boundary_find (GeglBuffer          *buffer,
                     const GeglRectangle *region,
+                    const Babl          *format,
                     GimpBoundaryType     type,
                     int                  x1,
                     int                  y1,
                     int                  x2,
                     int                  y2,
-                    guchar               threshold,
+                    gfloat               threshold,
                     int                 *num_segs)
 {
   GimpBoundary  *boundary;
@@ -167,6 +169,9 @@ gimp_boundary_find (GeglBuffer          *buffer,
 
   g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
   g_return_val_if_fail (num_segs != NULL, NULL);
+  g_return_val_if_fail (format != NULL, NULL);
+  g_return_val_if_fail (babl_format_get_bytes_per_pixel (format) ==
+                        sizeof (gfloat), NULL);
 
   if (region)
     {
@@ -178,7 +183,8 @@ gimp_boundary_find (GeglBuffer          *buffer,
       rect.height = gegl_buffer_get_height (buffer);
     }
 
-  boundary = generate_boundary (buffer, &rect, type, x1, y1, x2, y2, threshold);
+  boundary = generate_boundary (buffer, &rect, format, type,
+                                x1, y1, x2, y2, threshold);
 
   *num_segs = boundary->num_segs;
 
@@ -477,8 +483,7 @@ gimp_boundary_add_seg (GimpBoundary *boundary,
 
 static void
 find_empty_segs (const GeglRectangle *region,
-                 const guchar        *line_data,
-                 gint                 bpp,
+                 const gfloat        *line_data,
                  gint                 scanline,
                  gint                 empty_segs[],
                  gint                 max_empty,
@@ -488,7 +493,7 @@ find_empty_segs (const GeglRectangle *region,
                  gint                 y1,
                  gint                 x2,
                  gint                 y2,
-                 guchar               threshold)
+                 gfloat               threshold)
 {
   gint start = 0;
   gint end   = 0;
@@ -532,8 +537,7 @@ find_empty_segs (const GeglRectangle *region,
 
   endx = end;
 
-  line_data += bpp * start;
-  line_data += bpp - 1;
+  line_data += start;
 
   for (x = start; x < end;)
     {
@@ -555,7 +559,7 @@ find_empty_segs (const GeglRectangle *region,
                   val = -1;
                 }
 
-              line_data += bpp;
+              line_data++;
 
               if (last != val)
                 empty_segs[l_num_empty++] = x;
@@ -574,7 +578,7 @@ find_empty_segs (const GeglRectangle *region,
               else
                 val = -1;
 
-              line_data += bpp;
+              line_data++;
 
               if (last != val)
                 empty_segs[l_num_empty++] = x;
@@ -657,18 +661,17 @@ make_horiz_segs (GimpBoundary *boundary,
 static GimpBoundary *
 generate_boundary (GeglBuffer          *buffer,
                    const GeglRectangle *region,
+                   const Babl          *format,
                    GimpBoundaryType     type,
                    gint                 x1,
                    gint                 y1,
                    gint                 x2,
                    gint                 y2,
-                   guchar               threshold)
+                   gfloat               threshold)
 {
   GimpBoundary  *boundary;
-  const Babl    *format;
   GeglRectangle  line_rect = { 0, };
-  guchar        *line_data;
-  gint           bpp;
+  gfloat        *line_data;
   gint           scanline;
   gint           i;
   gint           start, end;
@@ -680,14 +683,10 @@ generate_boundary (GeglBuffer          *buffer,
 
   boundary = gimp_boundary_new (region);
 
-  /* XXX use an appropriate format here */
-  format = gegl_buffer_get_format (buffer);
-  bpp = babl_format_get_bytes_per_pixel (format);
-
   line_rect.width  = gegl_buffer_get_width (buffer);
   line_rect.height = 1;
 
-  line_data = g_alloca (bpp * line_rect.width);
+  line_data = g_alloca (sizeof (gfloat) * line_rect.width);
 
   start = 0;
   end   = 0;
@@ -704,7 +703,7 @@ generate_boundary (GeglBuffer          *buffer,
     }
 
   /*  Find the empty segments for the previous and current scanlines  */
-  find_empty_segs (region, NULL, bpp,
+  find_empty_segs (region, NULL,
                    start - 1, boundary->empty_segs_l,
                    boundary->max_empty_segs, &num_empty_l,
                    type, x1, y1, x2, y2,
@@ -715,7 +714,7 @@ generate_boundary (GeglBuffer          *buffer,
                    line_data, GEGL_AUTO_ROWSTRIDE,
                    GEGL_ABYSS_NONE);
 
-  find_empty_segs (region, line_data, bpp,
+  find_empty_segs (region, line_data,
                    start, boundary->empty_segs_c,
                    boundary->max_empty_segs, &num_empty_c,
                    type, x1, y1, x2, y2,
@@ -732,7 +731,7 @@ generate_boundary (GeglBuffer          *buffer,
                          line_data, GEGL_AUTO_ROWSTRIDE,
                          GEGL_ABYSS_NONE);
 
-      find_empty_segs (region, line_data, bpp,
+      find_empty_segs (region, line_data,
                        scanline + 1, boundary->empty_segs_n,
                        boundary->max_empty_segs, &num_empty_n,
                        type, x1, y1, x2, y2,
diff --git a/app/core/gimpboundary.h b/app/core/gimpboundary.h
index fabda66..29049ad 100644
--- a/app/core/gimpboundary.h
+++ b/app/core/gimpboundary.h
@@ -20,7 +20,7 @@
 
 
 /* half intensity for mask */
-#define GIMP_BOUNDARY_HALF_WAY 127
+#define GIMP_BOUNDARY_HALF_WAY 0.5
 
 
 typedef enum
@@ -43,12 +43,13 @@ struct _GimpBoundSeg
 
 GimpBoundSeg * gimp_boundary_find      (GeglBuffer          *buffer,
                                         const GeglRectangle *region,
+                                        const Babl          *format,
                                         GimpBoundaryType     type,
                                         gint                 x1,
                                         gint                 y1,
                                         gint                 x2,
                                         gint                 y2,
-                                        guchar               threshold,
+                                        gfloat               threshold,
                                         gint                *num_segs);
 GimpBoundSeg * gimp_boundary_sort      (const GimpBoundSeg  *segs,
                                         gint                 num_segs,
diff --git a/app/core/gimpbrush-boundary.c b/app/core/gimpbrush-boundary.c
index 98eec01..3d2e863 100644
--- a/app/core/gimpbrush-boundary.c
+++ b/app/core/gimpbrush-boundary.c
@@ -50,11 +50,12 @@ gimp_brush_transform_boundary_exact (GimpBrush *brush,
       buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) mask);
 
       bound_segs = gimp_boundary_find (buffer, NULL,
+                                       babl_format ("Y float"),
                                        GIMP_BOUNDARY_WITHIN_BOUNDS,
                                        0, 0,
                                        gegl_buffer_get_width  (buffer),
                                        gegl_buffer_get_height (buffer),
-                                       0,
+                                       0.0,
                                        &n_bound_segs);
 
       g_object_unref (buffer);
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index 7ad30e8..a1fc90a 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -995,6 +995,7 @@ gimp_channel_real_boundary (GimpChannel         *channel,
           buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel));
 
           channel->segs_out = gimp_boundary_find (buffer, &rect,
+                                                  babl_format ("Y float"),
                                                   GIMP_BOUNDARY_IGNORE_BOUNDS,
                                                   x1, y1, x2, y2,
                                                   GIMP_BOUNDARY_HALF_WAY,
@@ -1007,6 +1008,7 @@ gimp_channel_real_boundary (GimpChannel         *channel,
           if (x2 > x1 && y2 > y1)
             {
               channel->segs_in = gimp_boundary_find (buffer, NULL,
+                                                     babl_format ("Y float"),
                                                      GIMP_BOUNDARY_WITHIN_BOUNDS,
                                                      x1, y1, x2, y2,
                                                      GIMP_BOUNDARY_HALF_WAY,
diff --git a/app/core/gimplayer-floating-sel.c b/app/core/gimplayer-floating-sel.c
index ab3f4d9..6eb00db 100644
--- a/app/core/gimplayer-floating-sel.c
+++ b/app/core/gimplayer-floating-sel.c
@@ -215,6 +215,7 @@ floating_sel_boundary (GimpLayer *layer,
           buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
 
           layer->fs.segs = gimp_boundary_find (buffer, NULL,
+                                               babl_format ("A float"),
                                                GIMP_BOUNDARY_WITHIN_BOUNDS,
                                                0, 0, width, height,
                                                GIMP_BOUNDARY_HALF_WAY,
diff --git a/app/gegl/gimp-gegl.c b/app/gegl/gimp-gegl.c
index 758508e..af0b471 100644
--- a/app/gegl/gimp-gegl.c
+++ b/app/gegl/gimp-gegl.c
@@ -134,6 +134,12 @@ gimp_gegl_init (Gimp *gimp)
                    babl_component ("A"),
                    NULL);
 
+  babl_format_new ("name", "A float",
+                   babl_model ("R'G'B'A"),
+                   babl_type ("float"),
+                   babl_component ("A"),
+                   NULL);
+
   babl_format_new ("name", "A double",
                    babl_model ("R'G'B'A"),
                    babl_type ("double"),
diff --git a/app/tools/gimpregionselecttool.c b/app/tools/gimpregionselecttool.c
index 732de58..63c2399 100644
--- a/app/tools/gimpregionselecttool.c
+++ b/app/tools/gimpregionselecttool.c
@@ -369,6 +369,7 @@ gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel,
   buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (region_sel->region_mask));
 
   segs = gimp_boundary_find (buffer, NULL,
+                             babl_format ("Y float"),
                              GIMP_BOUNDARY_WITHIN_BOUNDS,
                              0, 0,
                              gimp_item_get_width  (GIMP_ITEM (region_sel->region_mask)),



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