1
votes

I need to fill this greyscale picture with some color , for example red. I thought to use Flood Fill algorithm because I need to fill at some certain points.

I found this method.But the result has some ugly white parts, because of the anti aliasing of the picture's lines.

in my code : Color targetColor= White, Color replacementColor=Red.

I think I need to change the replacement into more grey colors, not only white.

Should I stick with this method and change a little? or to find something else? If yes, what to change?

I did tried also this link ,but it doesn't work:

noblemaster.com/public/download/FloodFill.java.html

link for the images:

image without red color

image with filled red color

 public void floodFill(BufferedImage image, Point node, Color targetColor, Color replacementColor) {
        int width = image.getWidth();
        int height = image.getHeight();
        int target = targetColor.getRGB();
        int replacement = replacementColor.getRGB();
        if (target != replacement) {
          Deque<Point> queue = new LinkedList<Point>();
          do {
            int x = node.x;
            int y = node.y;
            while (x > 0 && image.getRGB(x - 1, y) == target) {
              x--;
            }
            boolean spanUp = false;
            boolean spanDown = false;
            while (x < width && image.getRGB(x, y) == target) {
              image.setRGB(x, y, replacement);
              if (!spanUp && y > 0 && image.getRGB(x, y - 1) == target) {
                queue.add(new Point(x, y - 1));
                spanUp = true;
              } else if (spanUp && y > 0 && image.getRGB(x, y - 1) != target) {
                spanUp = false;
              }
              if (!spanDown && y < height - 1 && image.getRGB(x, y + 1) == target) {
                queue.add(new Point(x, y + 1));
                spanDown = true;
              } else if (spanDown && y < height - 1 && image.getRGB(x, y + 1) != target) {
                spanDown = false;
              }
              x++;
            }
          } while ((node = queue.pollFirst()) != null);
        }
      }
1
Probably you shouldn't compare it with the "exact" white color. Try calculating the distance of the pixel with white and if it is less than some X value you should paint it red too.raven
Ok it works, but still there is still something that I missed. If I want to change from white to transparency. Now color distance cannot be done because rgb doesn't take to account an alpha component. But I think it's for another question..Yonatan Setbon

1 Answers

1
votes

This is what I did at the end and this is the final picture.

distanceOfColor is a parameter, in my case a good number was in between 300-400 more than that it erased all the grey color anti-aliasing.

 public void floodFill(BufferedImage image, Point node, Color targetColor, Color replacementColor) {
        int width = image.getWidth();
        int height = image.getHeight();
        int target = targetColor.getRGB();
        int replacement = replacementColor.getRGB();
        int distanceOfColor=320;
        if (target != replacement) {
          Deque<Point> queue = new LinkedList<Point>();
          do {
            int x = node.x;
            int y = node.y;
            while (x > 0 && ColorDistance(image.getRGB(x - 1, y), target)<=distanceOfColor) {
              x--;
            }
            boolean spanUp = false;
            boolean spanDown = false;
            while (x < width && ColorDistance(image.getRGB(x, y), target) <=distanceOfColor) {
              image.setRGB(x, y, replacement);
              if (!spanUp && y > 0 && image.getRGB(x, y - 1) == target) {
                queue.add(new Point(x, y - 1));
                spanUp = true;
              } else if (spanUp && y > 0 && ColorDistance(image.getRGB(x, y - 1), target) >distanceOfColor) {
                spanUp = false;
              }
              if (!spanDown && y < height - 1 && ColorDistance(image.getRGB(x, y + 1), target) <=distanceOfColor) {
                queue.add(new Point(x, y + 1));
                spanDown = true;
              } else if (spanDown && y < height - 1 && ColorDistance(image.getRGB(x, y + 1), target) >distanceOfColor) {
                spanDown = false;
              }
              x++;
            }
          } while ((node = queue.pollFirst()) != null);
        }
      }