Метод нерекурсивного наполнителя
Я делаю нерекурсивный метод заливки в Java, который использует координаты нажатого пикселя (x,y) и цветовой код в качестве входных данных. img является буферизованным изображением.
Код работает, но только для больших простых фигур (например, квадратов), а иногда и не заполняет даже их. Как это можно исправить, чтобы работать всегда и с любой формой?
public void floodFillNoRecursion (int x, int y, int color) {
if (img.getRGB(x, y)!=Color.BLACK.getRGB()) {
return;
} else {
int x1=x;
int y1=y;
img.setRGB(x, y, color);
for (int i=0;i<img.getHeight();i++) {
for (int j=0;j<img.getWidth();j++){
if (img.getRGB(x1+1, y1)==Color.BLACK.getRGB()){
x1++;
img.setRGB(x1, y1, color);
}
else if (img.getRGB(x1, y1+1)==Color.BLACK.getRGB()){
y1++;
img.setRGB(x1, y1, color);
}
else if (img.getRGB(x1, y1-1)==Color.BLACK.getRGB()){
y1--;
img.setRGB(x1, y1, color);
}
else if (img.getRGB(x1-1, y1)==Color.BLACK.getRGB()){
x1--;
img.setRGB(x1, y1, color);
}
}}
}}
2 ответа
Я думаю, что проблема заключается в увеличении и уменьшении переменных x1 и y1. Например, когда img.getRGB(x1+1, y1)==Color.BLACK.getRGB()
это правда и img.getRGB(x1-1, y1)==Color.BLACK.getRGB()
Это правда, что вы сначала увеличиваете переменную x1 и затем decrmenet, поэтому в следующем цикле for ваш x1 совпадает с предыдущей итерацией.
Я предлагаю использовать другой подход, чтобы избежать ошибки, которую вы делаете при уменьшении / увеличении ваших переменных:
(Псевдо-код!)
void floodfill( Image img, int startX, int startY, int borderColor )
{
Point startPoint = new Point(startX,startY);
if( !isNoBorder(startPoint, img, borderColor ) return;
List<Point> workList = new ArrayList<Point>();
workList.Add( startPoint );
while( workList.size() > 0 )
{
Point p = workList.remove(0);
Point p1 = new Point( p.X+1, p.Y );
Point p2 = new Point( p.X-1, p.Y );
Point p3 = new Point( p.X, p.Y+1 );
Point p4 = new Point( p.X, p.Y-1 );
if( isNoBorder(p1, img, borderColor) && !workList.contains( p1 ) ) workList.Add( p1 );
// same for p2-4
img.setRGB( p.X, p.Y, borderColor );
}
}
boolean isNoBorder( Point p, Image img, int borderColor ){
return p.X >= 0 && p.Y >= 0 && p.X < img.getWidth() && p.Y < img.getHeight() && img.getRGB(p.X,p.Y) != borderColor ;
}