通过将递归限制为处理图像的一小部分,可以避免堆栈溢出。以下代码将处理区域的大小限制为
SIZE
.
请注意,它还减少了调用递归方法的次数(请参见注释)。
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ImageColoring {
private static final int COLOR_TO_REPLACE = 0;
private static final int NEW_COLOR = -15073025;
private BufferedImage image;
private static final int SIZE = 10;
public ImageColoring(BufferedImage image) {
this.image = image;
}
public BufferedImage colorImage(){
for(int i = 0; i<image.getWidth();i++){
for(int j =0;j<image.getHeight();j++){
if(image.getRGB(i,j) == COLOR_TO_REPLACE){
fill(i,j);
}
}
}
return image;
}
private void fill(int x, int y){
if((x<0) || (y<0) || (x>=image.getWidth()) || (y>=image.getHeight())) {
return;
}
if(image.getRGB(x,y)!= COLOR_TO_REPLACE) {
return;
}
int xMax = ((x + SIZE) > image.getWidth()) ? image.getWidth() : x + SIZE ;
int yMax = ((y + SIZE) > image.getHeight()) ? image.getHeight() : y + SIZE;
while(fill(x, xMax, y, yMax)) {
x = xMax; y = yMax;
xMax = ((x + SIZE) > image.getWidth()) ? image.getWidth() : x + SIZE ;
yMax = ((y + SIZE) > image.getHeight()) ? image.getHeight() : y + SIZE;
}
}
private boolean fill(int x, int xMax, int y, int yMax){
if( (x>=xMax) || (y>=yMax)) {
return false;
}
if(image.getRGB(x,y)!= COLOR_TO_REPLACE) {
return false;
}
image.setRGB(x,y,NEW_COLOR);
if(fill(x+1,y, xMax, yMax) ||
//fill(x-1,y, xMax, yMax)|| not needed. it enough to progress
//fill(x,y-1, xMax, yMax) || in one direction to cover all
fill(x,y+1, xMax, yMax) ) { return true; };
return false;
}
public static void main(String[] args) throws IOException {
String imagePath = "https://upload.wikimedia.org/wikipedia/commons/3/3f/Crystal_Project_bug.png";
URL url = new URL(imagePath);
ImageColoring ic = new ImageColoring(ImageIO.read(url));
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel grid = new JPanel(new GridLayout(1, 2, 15, 15));
grid.add(new JLabel(new ImageIcon(ImageIO.read(url))));
grid.add(new JLabel(new ImageIcon(ic.colorImage())));
window.add(grid);
window.pack();
window.setVisible(true);
}
}
(必须修改变色逻辑)