1

私のプログラムは、boundaryFill4 メソッドで指定した色 (最初は黒と白) で不規則な形状を塗りつぶすことになっています。ここに myImage.png へのリンクがあります : https://dl.dropbox.com/u/41007907/myImage.png

  import java.awt.Color;
  import java.awt.Container;
  import java.awt.Image;
  import java.awt.image.BufferedImage;
  import javax.swing.ImageIcon;
  import javax.swing.JFrame;
  import javax.swing.JLabel;

      public class MyPolygon extends JFrame {

private JLabel my;

public MyPolygon() throws InterruptedException {
    createMy();
}

private void createMy() throws InterruptedException {
    Container contentPane = getContentPane();
    contentPane.setBackground(Color.WHITE);
    contentPane.setLayout(null);
    contentPane.setSize(1000, 700);

    my = new JLabel();
    my.setIcon(new ImageIcon("myImage.png"));
    my.setBounds(50, 50, 300, 300);
    contentPane.add(my);

    setSize(1000, 700);
    setVisible(true);
    setLocationRelativeTo(null);

    int fill = 100;
    boundaryFill4(100, 100, fill, 50);
}

// Flood Fill method
public void boundaryFill4(int x, int y, int fill, int boundary) {
    int current;
    current = getPixel(x, y);
    if ((current >= boundary) && (current != fill)) {
        setPixel(x, y, fill);
        boundaryFill4(x + 1, y, fill, boundary);
        boundaryFill4(x - 1, y, fill, boundary);
        boundaryFill4(x, y + 1, fill, boundary);
        boundaryFill4(x, y - 1, fill, boundary);
    }
}

// Getting the color integer at specified point(x, y)
private int getPixel(int x, int y) {
    Image img = ((ImageIcon) my.getIcon()).getImage();
    BufferedImage buffered = new BufferedImage(img.getWidth(null),
            img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    buffered.getGraphics().drawImage(img, 0, 0, null);
    Color c = new Color(buffered.getRGB(x, y));
    int current = buffered.getRGB(x, y);
    return current;
}

// Setting the color integer to a specified point(x, y)
private void setPixel(int x, int y, int fill) {
    Image img = ((ImageIcon) my.getIcon()).getImage();
    BufferedImage buffered = new BufferedImage(img.getWidth(null),
            img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    buffered.getGraphics().drawImage(img, 0, 0, null);
    int red = fill;
    int green = fill;
    int blue = fill;
    Color c = new Color(buffered.getRGB(x, y));
    c = new Color(red, green, blue);
    buffered.setRGB(x, y, c.getRGB());
}

// Main method
public static void main(String args[]) throws InterruptedException {
    MyPolygon my = new MyPolygon();
    my.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

StackOverflow エラーが発生するのはなぜですか? コードが機能するように修正するにはどうすればよいですか?

4

3 に答える 3

3

boundaryFill4再帰的アプローチ(それ自体を呼び出す)を非再帰的アプローチに変換しようとすることができます。このようにして、JVM スタックはオーバーフローしません。

もう 1 つのオプションは、スタックのサイズを増やすことです。Java コール スタックの最大深度はどれくらいですか? を参照してください。

于 2013-04-09T08:32:08.993 に答える
2

StackOverflowException は、再帰がメモリに対して深すぎるか、終了していないことを意味します。小さい画像で試してください。これで問題が解決しない場合は、再帰終了条件に何か問題があります。( setPixel() と getPixel は本当に画像を変更しますか? JUnitTestを書きます)

また、setPixel および getPixel メソッドを単純化する必要があります。それらは複雑すぎます。設定または取得するすべてのピクセルに対して、新しい BufferedImage-Instance を作成し、1 つのピクセルを設定した後に破棄します。BufferedImage を保存して再利用できます。

于 2013-04-09T08:32:57.987 に答える
1

メソッドをデバッグする必要boundaryFill4があります。ここで無限ループが発生します。単純なケースを使用して、メソッドがどのように反応するかを追跡します。

さらに、再帰の各反復で画像の書き込み/読み取りを避ける必要があります。最初に画像を表す適切で効率的なデータ構造をインスタンス化し、次にこのデータ構造を変更し、アルゴリズムが終了したら、結果を画像として書き込みます。

于 2013-04-09T08:32:06.507 に答える