Task: Bitmap_Flood fill







Python: from collections import deque

image_file = "image.png"
fill_color = color(250, 0, 0)
tolerance = 15
allowed = False

def setup():
    global img
    size(600, 400)
    img = loadImage(image_file)
    fill(0, 0, 100)
    textSize(18)
    show()
    
def show():
    image(img, 0, 0, width, height)
    text("Tolerance = {}    (Use mouse wheel to change)".format(tolerance),
         100, height - 30)
    text("Right click to reset", 100, height - 10)
 
def draw():
    global allowed
    if allowed:
        show()
        allowed = False

def mousePressed():
    global allowed, img
    if mouseButton == RIGHT:
        img = loadImage(image_file)
    else:
        img.loadPixels()
        flood(mouseX, mouseY)
        img.updatePixels()
    allowed = True    

def mouseWheel(event):
    global allowed, tolerance
    e = event.getCount()
    tolerance += 2 * e
    if tolerance > 128:
        tolerance = 128
    if tolerance < 0:
        tolerance = 0
    allowed = True

def flood(x, y):
    target_color = img.pixels[pixel_position(mouseX, mouseY)]
    if target_color != fill_color:
        queue = deque()
        queue.append((x, y))
        while len(queue) > 0:
            p_x, p_y = queue.popleft()
            if (check(p_x, p_y, target_color)):
                queue.append((p_x, p_y - 1))
                queue.append((p_x, p_y + 1))
                queue.append((p_x - 1, p_y))
                queue.append((p_x + 1, p_y))

def pixel_position(x, y):
    return x + (y * img.width)

def check(x, y, target_color):
    if x < 0 or y < 0 or y >= img.height or x >= img.width:
        return False
    pp = img.pixels[pixel_position(x, y)]
    test_tolerance = (abs(green(target_color) - green(pp)) < tolerance
                      and abs(red(target_color) - red(pp)) < tolerance
                      and abs(blue(target_color) - blue(pp)) < tolerance)
    if not test_tolerance:
        return False
    img.pixels[pixel_position(x, y)] = fill_color
    return True





Ada: procedure Flood_Fill
          (  Picture  : in out Image;
             From     : Point;
             Fill     : Pixel;
             Replace  : Pixel;
             Distance : Luminance := 20
          )  is
   function Diff (A, B : Luminance) return Luminance is
      pragma Inline (Diff);
   begin
      if A > B then
         return A - B;
      else
         return B - A;
      end if;
   end Diff;

   function "-" (A, B : Pixel) return Luminance is
      pragma Inline ("-");
   begin
      return Luminance'Max (Luminance'Max (Diff (A.R, B.R), Diff (A.G, B.G)), Diff (A.B, B.B));
   end "-";
   procedure Column (From : Point);
   procedure Row (From : Point);

   Visited : array (Picture'Range (1), Picture'Range (2)) of Boolean :=
      (others => (others => False));

   procedure Column (From : Point) is
      X1 : Positive := From.X;
      X2 : Positive := From.X;
   begin
      Visited (From.X, From.Y) := True;
      for X in reverse Picture'First (1)..From.X - 1 loop
         exit when Visited (X, From.Y);
         declare
            Color : Pixel renames Picture (X, From.Y);
         begin
            Visited (X, From.Y) := True;
            exit when Color - Replace > Distance;
            Color := Fill;
            X1    := X;
         end;
      end loop;
      for X in From.X + 1..Picture'Last (1) loop
         exit when Visited (X, From.Y);
         declare
            Color : Pixel renames Picture (X, From.Y);
         begin
            Visited (X, From.Y) := True;
            exit when Color - Replace > Distance;
            Color := Fill;
            X2    := X;
         end;
      end loop;
      for X in X1..From.X - 1 loop
         Row ((X, From.Y));
      end loop;
      for X in From.X + 1..X2 loop
         Row ((X, From.Y));
      end loop;
   end Column;

   procedure Row (From : Point) is
      Y1 : Positive := From.Y;
      Y2 : Positive := From.Y;
   begin
      Visited (From.X, From.Y) := True;
      for Y in reverse Picture'First (2)..From.Y - 1 loop
         exit when Visited (From.X, Y);
         declare
            Color : Pixel renames Picture (From.X, Y);
         begin
            Visited (From.X, Y) := True;
            exit when Color - Replace > Distance;
            Color := Fill;
            Y1    := Y;
         end;
      end loop;
      for Y in From.Y + 1..Picture'Last (2) loop
         exit when Visited (From.X, Y);
         declare
            Color : Pixel renames Picture (From.X, Y);
         begin
            Visited (From.X, Y) := True;
            exit when Color - Replace > Distance;
            Color := Fill;
            Y2    := Y;
         end;
      end loop;
      for Y in Y1..From.Y - 1 loop
         Column ((From.X, Y));
      end loop;
      for Y in From.Y + 1..Y2 loop
         Column ((From.X, Y));
      end loop;
   end Row;

   Color : Pixel renames Picture (From.X, From.Y);
begin
   if Color - Replace <= Distance then
      Visited (From.X, From.Y) := True;
      Color := Fill;
      Column (From);
   end if;
end Flood_Fill;