implement a flood_fill that stops at a given color rather than filling
authorTony Cook <tony@develop=help.com>
Tue, 27 Jun 2006 12:20:47 +0000 (12:20 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 27 Jun 2006 12:20:47 +0000 (12:20 +0000)
a region of the color at the start poiint.

from perl you can call flood_fill() with a border parameter to specify
a fill to border.

from the API call the i_flood_fill_border() or i_flood_cfill_border()
function.

12 files changed:
Imager.pm
Imager.xs
draw.c
fills.c
imager.h
imext.c
imext.h
imexttypes.h
lib/Imager/APIRef.pod
lib/Imager/Draw.pod
t/t20fill.t
t/t82inline.t

index 7107bd0..c8bd5b5 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -2655,26 +2655,69 @@ sub flood_fill {
     return undef;
   }
 
-  if ($opts{fill}) {
-    unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
-      # assume it's a hash ref
-      require 'Imager/Fill.pm';
-      unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
-        $self->{ERRSTR} = $Imager::ERRSTR;
-        return;
+  if ($opts{border}) {
+    my $border = _color($opts{border});
+    unless ($border) {
+      $self->_set_error($Imager::ERRSTR);
+      return;
+    }
+    if ($opts{fill}) {
+      unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
+       # assume it's a hash ref
+       require Imager::Fill;
+       unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
+         $self->{ERRSTR} = $Imager::ERRSTR;
+         return;
+       }
+      }
+      $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'}, 
+                                $opts{fill}{fill}, $border);
+    }
+    else {
+      my $color = _color($opts{'color'});
+      unless ($color) {
+       $self->{ERRSTR} = $Imager::ERRSTR;
+       return;
       }
+      $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'}, 
+                               $color, $border);
+    }
+    if ($rc) { 
+      return $self; 
+    } 
+    else { 
+      $self->{ERRSTR} = $self->_error_as_msg(); 
+      return;
     }
-    $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
   }
   else {
-    my $color = _color($opts{'color'});
-    unless ($color) {
-      $self->{ERRSTR} = $Imager::ERRSTR;
+    if ($opts{fill}) {
+      unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
+       # assume it's a hash ref
+       require 'Imager/Fill.pm';
+       unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
+         $self->{ERRSTR} = $Imager::ERRSTR;
+         return;
+       }
+      }
+      $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
+    }
+    else {
+      my $color = _color($opts{'color'});
+      unless ($color) {
+       $self->{ERRSTR} = $Imager::ERRSTR;
+       return;
+      }
+      $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
+    }
+    if ($rc) { 
+      return $self; 
+    } 
+    else { 
+      $self->{ERRSTR} = $self->_error_as_msg(); 
       return;
     }
-    $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
-  }
-  if ($rc) { $self; } else { $self->{ERRSTR} = $self->_error_as_msg(); return (); }
+  } 
 }
 
 sub setpixel {
index ce82ff3..962ea56 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -1498,6 +1498,22 @@ i_flood_cfill(im,seedx,seedy,fill)
               int     seedy
      Imager::FillHandle     fill
 
+undef_int
+i_flood_fill_border(im,seedx,seedy,dcol, border)
+    Imager::ImgRaw     im
+              int     seedx
+              int     seedy
+     Imager::Color     dcol
+     Imager::Color     border
+
+undef_int
+i_flood_cfill_border(im,seedx,seedy,fill, border)
+    Imager::ImgRaw     im
+              int     seedx
+              int     seedy
+     Imager::FillHandle     fill
+     Imager::Color     border
+
 
 void
 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
diff --git a/draw.c b/draw.c
index b9ab166..8cbe445 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -5,6 +5,10 @@
 
 #include <limits.h>
 
+static void
+cfill_from_btm(i_img *im, i_fill_t *fill, struct i_bitmap *btm, 
+              int bxmin, int bxmax, int bymin, int bymax);
+
 void
 i_mmarray_cr(i_mmarray *ar,int l) {
   int i;
@@ -1086,33 +1090,46 @@ crdata(int left,int right,int dadl,int dadr,int y, int dir) {
 
 /* i_ccomp compares two colors and gives true if they are the same */
 
+typedef int (*ff_cmpfunc)(i_color const *c1, i_color const *c2, int channels);
+
 static int
-i_ccomp(i_color *val1,i_color *val2,int ch) {
+i_ccomp_normal(i_color const *val1, i_color const *val2, int ch) {
   int i;
-  for(i=0;i<ch;i++) if (val1->channel[i] !=val2->channel[i]) return 0;
+  for(i = 0; i < ch; i++) 
+    if (val1->channel[i] !=val2->channel[i])
+      return 0;
   return 1;
 }
 
+static int
+i_ccomp_border(i_color const *val1, i_color const *val2, int ch) {
+  int i;
+  for(i = 0; i < ch; i++) 
+    if (val1->channel[i] !=val2->channel[i])
+      return 1;
+  return 0;
+}
 
 static int
-i_lspan(i_img *im, int seedx, int seedy, i_color *val) {
+i_lspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc) {
   i_color cval;
   while(1) {
     if (seedx-1 < 0) break;
     i_gpix(im,seedx-1,seedy,&cval);
-    if (!i_ccomp(val,&cval,im->channels)) break;
+    if (!cmpfunc(val,&cval,im->channels)) 
+      break;
     seedx--;
   }
   return seedx;
 }
 
 static int
-i_rspan(i_img *im, int seedx, int seedy, i_color *val) {
+i_rspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc) {
   i_color cval;
   while(1) {
     if (seedx+1 > im->xsize-1) break;
     i_gpix(im,seedx+1,seedy,&cval);
-    if (!i_ccomp(val,&cval,im->channels)) break;
+    if (!cmpfunc(val,&cval,im->channels)) break;
     seedx++;
   }
   return seedx;
@@ -1152,7 +1169,7 @@ i_rspan(i_img *im, int seedx, int seedy, i_color *val) {
 #define SET(x,y) btm_set(btm,x,y)
 
 /* INSIDE returns true if pixel is correct color and we haven't set it before. */
-#define INSIDE(x,y) ((!btm_test(btm,x,y) && ( i_gpix(im,x,y,&cval),i_ccomp(&val,&cval,channels)  ) ))
+#define INSIDE(x,y, seed) ((!btm_test(btm,x,y) && ( i_gpix(im,x,y,&cval),cmpfunc(seed,&cval,channels)  ) ))
 
 
 
@@ -1160,15 +1177,8 @@ i_rspan(i_img *im, int seedx, int seedy, i_color *val) {
 
 static struct i_bitmap *
 i_flood_fill_low(i_img *im,int seedx,int seedy,
-                 int *bxminp, int *bxmaxp, int *byminp, int *bymaxp) {
-
-  /*
-    int lx,rx;
-    int y;
-    int direction;
-    int dadLx,dadRx;
-    int wasIn=0;
-  */
+                 int *bxminp, int *bxmaxp, int *byminp, int *bymaxp,
+                i_color const *seed, ff_cmpfunc cmpfunc) {
   int ltx, rtx;
   int tx = 0;
 
@@ -1181,7 +1191,7 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
   struct i_bitmap *btm;
 
   int channels,xsize,ysize;
-  i_color cval,val;
+  i_color cval;
 
   channels = im->channels;
   xsize    = im->xsize;
@@ -1190,12 +1200,9 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
   btm = btm_new(xsize, ysize);
   st  = llist_new(100, sizeof(struct stack_element*));
 
-  /* Get the reference color */
-  i_gpix(im, seedx, seedy, &val);
-
   /* Find the starting span and fill it */
-  ltx = i_lspan(im, seedx, seedy, &val);
-  rtx = i_rspan(im, seedx, seedy, &val);
+  ltx = i_lspan(im, seedx, seedy, seed, cmpfunc);
+  rtx = i_rspan(im, seedx, seedy, seed, cmpfunc);
   for(tx=ltx; tx<=rtx; tx++) SET(tx, seedy);
 
   ST_PUSH(ltx, rtx, ltx, rtx, seedy+1,  1);
@@ -1220,10 +1227,10 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
 
 
     x = lx+1;
-    if ( lx >= 0 && (wasIn = INSIDE(lx, y)) ) {
+    if ( lx >= 0 && (wasIn = INSIDE(lx, y, seed)) ) {
       SET(lx, y);
       lx--;
-      while(INSIDE(lx, y) && lx > 0) {
+      while(INSIDE(lx, y, seed) && lx > 0) {
        SET(lx,y);
        lx--;
       }
@@ -1234,7 +1241,7 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
       /*  printf("x=%d\n",x); */
       if (wasIn) {
        
-       if (INSIDE(x, y)) {
+       if (INSIDE(x, y, seed)) {
          /* case 1: was inside, am still inside */
          SET(x,y);
        } else {
@@ -1247,7 +1254,7 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
        }
       } else {
        if (x > rx) goto EXT;
-       if (INSIDE(x, y)) {
+       if (INSIDE(x, y, seed)) {
          SET(x, y);
          /* case 3: Wasn't inside, am now: just found the start of a new run */
          wasIn = 1;
@@ -1295,6 +1302,7 @@ i_flood_fill(i_img *im, int seedx, int seedy, const i_color *dcol) {
   int bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
   int x, y;
+  i_color val;
 
   i_clear_error();
   if (seedx < 0 || seedx >= im->xsize ||
@@ -1303,7 +1311,11 @@ i_flood_fill(i_img *im, int seedx, int seedy, const i_color *dcol) {
     return 0;
   }
 
-  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax);
+  /* Get the reference color */
+  i_gpix(im, seedx, seedy, &val);
+
+  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax,
+                        &val, i_ccomp_normal);
 
   for(y=bymin;y<=bymax;y++)
     for(x=bxmin;x<=bxmax;x++)
@@ -1331,8 +1343,7 @@ undef_int
 i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
   int bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
-  int x, y;
-  int start;
+  i_color val;
 
   i_clear_error();
   
@@ -1342,7 +1353,102 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
     return 0;
   }
 
-  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax);
+  /* Get the reference color */
+  i_gpix(im, seedx, seedy, &val);
+
+  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax,
+                        &val, i_ccomp_normal);
+
+  cfill_from_btm(im, fill, btm, bxmin, bxmax, bymin, bymax);
+
+  btm_destroy(btm);
+  return 1;
+}
+
+/*
+=item i_flood_fill_border(im, seedx, seedy, color, border)
+
+=category Drawing
+=synopsis i_flood_fill_border(im, 50, 50, &color, &border);
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<color>, fill stops when the fill reaches a pixels with
+color I<border>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+=cut
+*/
+
+undef_int
+i_flood_fill_border(i_img *im, int seedx, int seedy, const i_color *dcol,
+                   const i_color *border) {
+  int bxmin, bxmax, bymin, bymax;
+  struct i_bitmap *btm;
+  int x, y;
+
+  i_clear_error();
+  if (seedx < 0 || seedx >= im->xsize ||
+      seedy < 0 || seedy >= im->ysize) {
+    i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
+    return 0;
+  }
+
+  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax,
+                        border, i_ccomp_border);
+
+  for(y=bymin;y<=bymax;y++)
+    for(x=bxmin;x<=bxmax;x++)
+      if (btm_test(btm,x,y)) 
+       i_ppix(im,x,y,dcol);
+  btm_destroy(btm);
+  return 1;
+}
+
+/*
+=item i_flood_cfill_border(im, seedx, seedy, fill, border)
+
+=category Drawing
+=synopsis i_flood_cfill_border(im, 50, 50, fill, border);
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<fill>, the fill stops when it reaches pixels of color
+I<border>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+=cut
+*/
+
+undef_int
+i_flood_cfill_border(i_img *im, int seedx, int seedy, i_fill_t *fill,
+                    const i_color *border) {
+  int bxmin, bxmax, bymin, bymax;
+  struct i_bitmap *btm;
+
+  i_clear_error();
+  
+  if (seedx < 0 || seedx >= im->xsize ||
+      seedy < 0 || seedy >= im->ysize) {
+    i_push_error(0, "i_flood_cfill_border: Seed pixel outside of image");
+    return 0;
+  }
+
+  btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax,
+                        border, i_ccomp_border);
+
+  cfill_from_btm(im, fill, btm, bxmin, bxmax, bymin, bymax);
+
+  btm_destroy(btm);
+
+  return 1;
+}
+
+static void
+cfill_from_btm(i_img *im, i_fill_t *fill, struct i_bitmap *btm, 
+              int bxmin, int bxmax, int bymin, int bymax) {
+  int x, y;
+  int start;
 
   if (im->bits == i_8_bits && fill->fill_with_color) {
     /* bxmax/bxmin are inside the image, hence this won't overflow */
@@ -1416,7 +1522,4 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
     if (work)
       myfree(work);
   }
-
-  btm_destroy(btm);
-  return 1;
 }
diff --git a/fills.c b/fills.c
index 05db1aa..e1af156 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -700,7 +700,7 @@ static i_color interp_i_color(i_color before, i_color after, double pos,
   pos -= floor(pos);
   for (ch = 0; ch < channels; ++ch)
     out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
-  if (out.channel[3])
+  if (channels > 3 && out.channel[3])
     for (ch = 0; ch < channels; ++ch)
       if (ch != 3) {
         int temp = out.channel[ch] * 255 / out.channel[3];
index 654bbe6..64c0c29 100644 (file)
--- a/imager.h
+++ b/imager.h
@@ -181,6 +181,8 @@ void i_poly_aa_cfill(i_img *im,int l,const double *x,const double *y,i_fill_t *f
 
 undef_int i_flood_fill  (i_img *im,int seedx,int seedy, const i_color *dcol);
 undef_int i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill);
+undef_int i_flood_fill_border  (i_img *im,int seedx,int seedy, const i_color *dcol, const i_color *border);
+undef_int i_flood_cfill_border(i_img *im, int seedx, int seedy, i_fill_t *fill, const i_color *border);
 
 
 /* image processing functions */
diff --git a/imext.c b/imext.c
index cc4cd0c..690cbe2 100644 (file)
--- a/imext.c
+++ b/imext.c
@@ -101,6 +101,9 @@ im_ext_funcs imager_function_table =
     i_set_image_file_limits,
     i_get_image_file_limits,
     i_int_check_image_file_limits,
+
+    i_flood_fill_border,
+    i_flood_cfill_border,
   };
 
 /* in general these functions aren't called by Imager internally, but
diff --git a/imext.h b/imext.h
index cb43c45..fd03832 100644 (file)
--- a/imext.h
+++ b/imext.h
@@ -173,6 +173,8 @@ extern im_ext_funcs *imager_function_ext_table;
 #define i_circle_aa(im, x, y, rad, val) ((im_extt->f_i_circle_aa)((im), (x), (y), (rad), (val)))
 #define i_flood_fill(im, seedx, seedy, dcol) ((im_extt->f_i_flood_fill)((im), (seedx), (seedy), (dcol)))
 #define i_flood_cfill(im, seedx, seedy, fill) ((im_extt->f_i_flood_cfill)((im), (seedx), (seedy), (fill)))
+#define i_flood_fill_border(im, seedx, seedy, dcol, border) ((im_extt->f_i_flood_fill_border)((im), (seedx), (seedy), (dcol), (border)))
+#define i_flood_cfill_border(im, seedx, seedy, fill, border) ((im_extt->f_i_flood_cfill_border)((im), (seedx), (seedy), (fill), (border)))
 
 #define i_copyto(im, src, x1, y1, x2, y2, tx, ty) \
   ((im_extt->f_i_copyto)((im), (src), (x1), (y1), (x2), (y2), (tx), (ty)))
index 6e8fbad..459fb03 100644 (file)
@@ -139,6 +139,8 @@ typedef struct {
   int (*f_i_set_image_file_limits)(int width, int height, int bytes);
   int (*f_i_get_image_file_limits)(int *width, int *height, int *bytes);
   int (*f_i_int_check_image_file_limits)(int width, int height, int channels, int sample_size);
+  int (*f_i_flood_fill_border)(i_img *im, int seedx, int seedy, const i_color *dcol, const i_color *border);
+  int (*f_i_flood_cfill_border)(i_img *im, int seedx, int seedy, i_fill_t *fill, const i_color *border);
 
   /* IMAGER_API_LEVEL 3 functions will be added here */
 } im_ext_funcs;
index 8aaadf4..0994ca5 100644 (file)
@@ -25,7 +25,9 @@ Imager::APIRef - Imager's C API.
   i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &color);
   i_circle_aa(im, 50, 50, 45, &color);
   i_flood_cfill(im, 50, 50, fill);
+  i_flood_cfill_border(im, 50, 50, fill, border);
   i_flood_fill(im, 50, 50, &color);
+  i_flood_fill_border(im, 50, 50, &color, &border);
 
   # Error handling
 
@@ -59,7 +61,7 @@ of angles in degrees from d1 to d2, with the color.
 
 
 =for comment
-From: Line 205 in draw.c
+From: Line 209 in draw.c
 
 =item i_arc_aa(im, x, y, rad, d1, d2, color)
 
@@ -69,7 +71,7 @@ the range of angles in degrees from d1 to d2, with the color.
 
 
 =for comment
-From: Line 330 in draw.c
+From: Line 334 in draw.c
 
 =item i_arc_aa_cfill(im, x, y, rad, d1, d2, fill)
 
@@ -79,7 +81,7 @@ the range of angles in degrees from d1 to d2, with the fill object.
 
 
 =for comment
-From: Line 356 in draw.c
+From: Line 360 in draw.c
 
 =item i_arc_cfill(im, x, y, rad, d1, d2, fill)
 
@@ -89,7 +91,7 @@ of angles in degrees from d1 to d2, with the fill object.
 
 
 =for comment
-From: Line 230 in draw.c
+From: Line 234 in draw.c
 
 =item i_box(im, x1, y1, x2, y2, color)
 
@@ -98,7 +100,7 @@ Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
 
 
 =for comment
-From: Line 516 in draw.c
+From: Line 520 in draw.c
 
 =item i_box_cfill(im, x1, y1, x2, y2, fill)
 
@@ -107,7 +109,7 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with fill.
 
 
 =for comment
-From: Line 559 in draw.c
+From: Line 563 in draw.c
 
 =item i_box_filled(im, x1, y1, x2, y2, color)
 
@@ -116,7 +118,7 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with color.
 
 
 =for comment
-From: Line 541 in draw.c
+From: Line 545 in draw.c
 
 =item i_circle_aa(im, x, y, rad, color)
 
@@ -126,7 +128,7 @@ color.
 
 
 =for comment
-From: Line 462 in draw.c
+From: Line 466 in draw.c
 
 =item i_flood_cfill(im, seedx, seedy, fill)
 
@@ -138,7 +140,20 @@ Returns false if (seedx, seedy) are outside the image.
 
 
 =for comment
-From: Line 1317 in draw.c
+From: Line 1329 in draw.c
+
+=item i_flood_cfill_border(im, seedx, seedy, fill, border)
+
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<fill>, the fill stops when it reaches pixels of color
+I<border>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+
+=for comment
+From: Line 1409 in draw.c
 
 =item i_flood_fill(im, seedx, seedy, color)
 
@@ -150,7 +165,20 @@ Returns false if (seedx, seedy) are outside the image.
 
 
 =for comment
-From: Line 1280 in draw.c
+From: Line 1287 in draw.c
+
+=item i_flood_fill_border(im, seedx, seedy, color, border)
+
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<color>, fill stops when the fill reaches a pixels with
+color I<border>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+
+=for comment
+From: Line 1369 in draw.c
 
 =item i_glin(im, l, r, y, colors)
 
@@ -161,7 +189,7 @@ Returns the number of pixels retrieved.
 
 
 =for comment
-From: Line 202 in imext.c
+From: Line 210 in imext.c
 
 =item i_glinf(im, l, r, y, colors)
 
@@ -173,7 +201,7 @@ Returns the number of pixels retrieved.
 
 
 =for comment
-From: Line 237 in imext.c
+From: Line 245 in imext.c
 
 =item i_gpal(im, x, r, y, indexes)
 
@@ -187,7 +215,7 @@ Always returns 0 for direct color images.
 
 
 =for comment
-From: Line 301 in imext.c
+From: Line 309 in imext.c
 
 =item i_gpix(im, x, y, color)
 
@@ -198,7 +226,7 @@ Returns 0 if the pixel was retrieved, or -1 if not.
 
 
 =for comment
-From: Line 130 in imext.c
+From: Line 138 in imext.c
 
 =item i_gpixf(im, x, y, fcolor)
 
@@ -210,7 +238,7 @@ Returns 0 if the pixel was retrieved, or -1 if not.
 
 
 =for comment
-From: Line 166 in imext.c
+From: Line 174 in imext.c
 
 =item i_gsamp(im, l, r, y, samp, chans, chan_count)
 
@@ -227,7 +255,7 @@ chan_count)
 
 
 =for comment
-From: Line 255 in imext.c
+From: Line 263 in imext.c
 
 =item i_gsampf(im, l, r, y, samp, chans, chan_count)
 
@@ -244,7 +272,7 @@ chan_count)
 
 
 =for comment
-From: Line 278 in imext.c
+From: Line 286 in imext.c
 
 =item i_line(im, x1, y1, x2, y2, val, endp)
 
@@ -261,7 +289,7 @@ Draw a line to image using bresenhams linedrawing algorithm
 
 
 =for comment
-From: Line 630 in draw.c
+From: Line 634 in draw.c
 
 =item i_line_aa(im, x1, x2, y1, y2, color, endp)
 
@@ -272,7 +300,7 @@ The point (x2, y2) is drawn only if endp is set.
 
 
 =for comment
-From: Line 834 in draw.c
+From: Line 838 in draw.c
 
 =item i_plin(im, l, r, y, colors)
 
@@ -284,7 +312,7 @@ Returns the number of pixels set.
 
 
 =for comment
-From: Line 184 in imext.c
+From: Line 192 in imext.c
 
 =item i_plinf(im, l, r, fcolors)
 
@@ -296,7 +324,7 @@ Returns the number of pixels set.
 
 
 =for comment
-From: Line 219 in imext.c
+From: Line 227 in imext.c
 
 =item i_ppal(im, x, r, y, indexes)
 
@@ -310,7 +338,7 @@ Always returns 0 for direct color images.
 
 
 =for comment
-From: Line 320 in imext.c
+From: Line 328 in imext.c
 
 =item i_ppix(im, x, y, color)
 
@@ -324,7 +352,7 @@ color to the image.
 
 
 =for comment
-From: Line 110 in imext.c
+From: Line 118 in imext.c
 
 =item i_ppixf(im, x, y, fcolor)
 
@@ -338,7 +366,7 @@ color to the image.
 
 
 =for comment
-From: Line 147 in imext.c
+From: Line 155 in imext.c
 
 
 =back
@@ -715,7 +743,7 @@ Always fails for direct color images.
 
 
 =for comment
-From: Line 339 in imext.c
+From: Line 347 in imext.c
 
 =item i_colorcount(im)
 
@@ -726,7 +754,7 @@ Returns -1 for direct images.
 
 
 =for comment
-From: Line 385 in imext.c
+From: Line 393 in imext.c
 
 =item i_findcolor(im, color, &entry)
 
@@ -741,7 +769,7 @@ Always fails on direct color images.
 
 
 =for comment
-From: Line 420 in imext.c
+From: Line 428 in imext.c
 
 =item i_getcolors(im, index, colors, count)
 
@@ -760,7 +788,7 @@ palette.
 
 
 =for comment
-From: Line 360 in imext.c
+From: Line 368 in imext.c
 
 =item i_maxcolors(im)
 
@@ -772,7 +800,7 @@ Returns -1 for direct color images.
 
 
 =for comment
-From: Line 402 in imext.c
+From: Line 410 in imext.c
 
 =item i_setcolors(im, index, colors, count)
 
@@ -790,7 +818,7 @@ Always fails on direct color images.
 
 
 =for comment
-From: Line 440 in imext.c
+From: Line 448 in imext.c
 
 
 =back
@@ -901,7 +929,7 @@ From: Line 320 in tags.c
 
 Retrieve a tag specified by name or code as an integer.
 
-On success sets the i_color *I<value> to the color and returns true.
+On success sets the int *I<value> to the integer and returns true.
 
 On failure returns false.
 
@@ -993,6 +1021,30 @@ Sets the given tag to the integer I<idata>
 From: Line 634 in tags.c
 
 
+=back
+
+
+=head1 UNDOCUMENTED
+
+The following API functions are undocumented so far, hopefully this
+will change:
+
+=over
+
+=item *
+
+B<i_get_image_file_limits>
+
+=item *
+
+B<i_int_check_image_file_limits>
+
+=item *
+
+B<i_set_image_file_limits>
+
+
+
 =back
 
 
index 54faff5..c8e471b 100644 (file)
@@ -406,13 +406,18 @@ fill - the fill for the filled circle.  See L<"Fill Parameters">
 
 =item flood_fill
 
-You can fill a region that all has the same color using the
-flood_fill() method, for example:
+X<flood_fill>You can fill a region that all has the same color using
+the flood_fill() method, for example:
 
   $img->flood_fill(x=>50, y=>50, color=>$color);
 
 will fill all regions the same color connected to the point (50, 50).
 
+Alternatively you can fill a region limited by a given border color:
+
+  # stop at the red border
+  $im->flood_fill(x=>50, y=>50, color=>$color, border=>"red");
+
 You can also fill with a complex fill:
 
   $img->flood_fill(x=>50, y=>50, fill=>{ hatch=>'cross1x1' });
@@ -434,6 +439,13 @@ Default: white.  Overridden by C<fill>.
 
 fill - the fill for the filled area.  See L<"Fill Parameters">
 
+=item *
+
+border - the border color of the region to be filled.  If this
+parameter is supplied flood_fill() will stop when it finds this color.
+If this is not supplied then a normal fill is done.  C<border> can be
+supplied as a L<"Color Parameter">.
+
 =back
 
 =item setpixel
index 146b05b..5cb4dc7 100644 (file)
@@ -1,7 +1,7 @@
 #!perl -w
 use strict;
 use lib 't';
-use Test::More tests => 52;
+use Test::More tests => 56;
 
 use Imager ':handy';
 use Imager::Fill;
@@ -169,7 +169,8 @@ $diff = Imager::i_img_diff($rffcmp, $ffim->{IMG});
 ok(!$diff, "oo flood fill difference");
 $ffim->flood_fill('x'=>50, 'y'=>50,
                   fill=> {
-                          hatch => 'check2x2'
+                          hatch => 'check2x2',
+                         fg => '0000FF',
                          });
 #                  fill=>{
 #                         fountain=>'radial',
@@ -178,6 +179,18 @@ $ffim->flood_fill('x'=>50, 'y'=>50,
 #                        });
 $ffim->write(file=>'testout/t20_ooflood.ppm');
 
+my $copy = $ffim->copy;
+ok($ffim->flood_fill('x' => 50, 'y' => 50,
+                    color => $red, border => '000000'),
+   "border solid flood fill");
+is(Imager::i_img_diff($ffim->{IMG}, $rffcmp), 0, "compare");
+ok($ffim->flood_fill('x' => 50, 'y' => 50,
+                    fill => { hatch => 'check2x2', fg => '0000FF', },
+                    border => '000000'),
+   "border cfill fill");
+is(Imager::i_img_diff($ffim->{IMG}, $copy->{IMG}), 0,
+   "compare");
+
 # test combining modes
 my $fill = NC(192, 128, 128, 128);
 my $target = NC(64, 32, 64);
index 9fa09e4..6768bef 100644 (file)
@@ -58,7 +58,7 @@ Imager do_lots(Imager src) {
   i_img *im = i_img_8_new(100, 100, 3);
   i_img *fill_im = i_img_8_new(5, 5, 3);
   i_img *testim;
-  i_color red, blue, temp_color;
+  i_color red, blue, green, black, temp_color;
   i_fcolor redf, bluef;
   i_fill_t *hatch, *fhatch_fill;
   i_fill_t *im_fill;
@@ -80,6 +80,10 @@ Imager do_lots(Imager src) {
   red.channel[3] = 255;
   blue.channel[0] = 0; blue.channel[1] = 0; blue.channel[2] = 255;
   blue.channel[3] = 255;
+  green.channel[0] = 0; green.channel[1] = 255; green.channel[2] = 0;
+  green.channel[3] = 255;
+  black.channel[0] = black.channel[1] = black.channel[2] = 0;
+  black.channel[3] = 255;
   hatch = i_new_fill_hatch(&red, &blue, 0, 1, NULL, 0, 0);
 
   i_box(im, 0, 0, 9, 9, &red);
@@ -134,6 +138,14 @@ Imager do_lots(Imager src) {
   i_box(im, 71, 11, 78, 18, &red);
   i_flood_cfill(im, 75, 15, hatch);
 
+  i_box_filled(im, 1, 21, 9, 24, &red);
+  i_box_filled(im, 1, 25, 9, 29, &blue);
+  i_flood_fill_border(im, 5, 25, &green, &black);
+
+  i_box_filled(im, 11, 21, 19, 24, &red);
+  i_box_filled(im, 11, 25, 19, 29, &blue);
+  i_flood_cfill_border(im, 15, 25, hatch, &black);
+
   i_fill_destroy(fount_fill);
   i_fill_destroy(fhatch_fill);
   i_fill_destroy(solid_fill);