代码之家  ›  专栏  ›  技术社区  ›  matip

递归遍历BufferedImage时发生StackOverflower错误

  •  1
  • matip  · 技术社区  · 6 年前

    这是我的密码。我做错什么了吗?这是个好办法吗?我应该试试别的吗?

        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;
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  0
  •   nmanh    6 年前

    我认为你的解决方案本身听起来很好很简短,问题是一个y=160的图像,如果你的代码创建一个至少160大小的y-1堆栈,甚至不考虑其他情况。

    我建议跳转到使用迭代的堆栈密集度较低的地方。 你可以在彼此下面做4个不同的循环(不是嵌套的!)。使其可读性降低,但至少减少了空间占用。

        2
  •  0
  •   c0der    6 年前

    通过将递归限制为处理图像的一小部分,可以避免堆栈溢出。以下代码将处理区域的大小限制为 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);
        }
    }
    

    (必须修改变色逻辑)

    enter image description here