Почему я получаю java.lang.StackruError при использовании алгоритма Flood Fill?
Моя программа должна заполнять нерегулярную фигуру цветом (вначале черным и белым), который я указываю в методе borderFill4. Вот ссылка на 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);
}
}
Почему я получаю ошибку Stackru? Как я могу исправить это, чтобы мой код работал?
3 ответа
StackruException означает, что ваша рекурсия слишком глубока для вашей памяти или не заканчивается. Попробуйте на маленьком изображении. Если это не решает проблему, значит что-то не так с вашим условием окончания рекурсии. (Действительно ли setPixel() и getPixel изменяют изображение? Написать JUnitTest)
Также вам действительно следует упростить методы setPixel и getPixel. Они слишком сложны. Для каждого установленного или полученного пикселя вы создаете новый экземпляр BufferedImage-Instance, а затем утилизируете его после установки ОДНОГО пикселя. Вы можете хранить и повторно использовать BufferedImage.
Вы можете попытаться преобразовать свой рекурсивный подход (boundaryFill4
называя себя) нерекурсивным. Таким образом, стек JVM не будет переполнен.
Другой вариант - увеличить размер стека - см. Какова максимальная глубина стека java-вызовов?
Вы должны отладить свой boundaryFill4
Метод: это где бесконечный цикл происходит. Используйте простые случаи, чтобы отслеживать, как метод реагирует.
Кроме того, вы должны избегать записи / чтения изображения на каждой итерации рекурсии. Создайте правильную и эффективную структуру данных, представляющую изображение в начале, затем измените эту структуру данных и, когда алгоритм завершится, запишите результаты в виде изображения.