我有一张政治地图图片,我想为其上的国家上色。我将图像加载到BufferedImage中,遍历像素并为白色着色。我使用递归方法来填充空格,即使它不是无限的(至少我是这么认为)我得到StackOverflowError。我使用的图像也不大,只有150x160像素。
这是我的代码。难道我做错了什么?这是不是很好的方法我应该尝试别的吗?
private final int[] COLORS = {-65536,-15073025,-16726785,-16711757,-16711919,-256,-417268,-455455,-5741663,-14194369,-14730152,-9885900};
private int colorCounter;
private BufferedImage image;
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) == -1){
fill(i,j);
incrementCounter();
}
}
}
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)!=-1) return;
image.setRGB(x,y,COLORS[colorCounter]);
fill(x+1,y);
fill(x-1,y);
fill(x,y+1);
fill(x,y-1);
}
private void incrementCounter(){
if(++colorCounter == COLORS.length) colorCounter = 0;
}
}
答案 0 :(得分:0)
我认为你的解决方案本身听起来很好而且简短,这是一个ay = 160的图像,可以让你的代码创建一个至少160的y-1的堆栈,甚至不考虑其他情况。
我建议跳转到堆栈密集度较低的迭代使用。 你可以在彼此之下做4个不同的循环(不嵌套!)。使其可读性降低,但至少不会占用太多空间。
答案 1 :(得分:0)
通过将递归限制为处理图像的一小部分,可以避免堆栈溢出。以下代码将处理区域的大小限制为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);
}
}
(必须修改颜色更改逻辑)