Bonjour, je suis en train d'expérimenter un algo de coloriage par diffusion et j'obtiens après quelques clic sur le dessin une erreur : Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError

Il semble que le problème vienne de la méthode floodLoop() de mon code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
// Recursively fills surrounding pixels of the old color
private void floodLoop(WritableRaster raster, int x, int y, int[] fill, int[] old) {
        Rectangle bounds = raster.getBounds();
        int[] aux = {255, 255, 255,old[3] };
 
        // finds the left side, filling along the way
        int fillL = x;
        do {
                raster.setPixel(fillL, y, fill);
                fillL--;
        } while (fillL >= 0 && isEqualRgba(raster.getPixel(fillL, y, aux), old));
        fillL++;
 
        // find the right right side, filling along the way
        int fillR = x;
        do {
                raster.setPixel(fillR, y, fill);
                fillR++;
        } while (fillR < bounds.width - 1 && isEqualRgba(raster.getPixel(fillR, y, aux), old));
        fillR--;
 
        // checks if applicable up or down
        for (int i = fillL; i <= fillR; i++) {
                if (y > 0 && isEqualRgba(raster.getPixel(i, y - 1, aux), old)) floodLoop(raster, i, y - 1,
                fill, old);
                if (y < bounds.height - 1 && isEqualRgba(raster.getPixel(i, y + 1, aux), old)) floodLoop(
                raster, i, y + 1, fill, old);
        }
}
Il me semble que cette erreur apparait en générale lorsqu'une boucle est mal contrôlée, pourtant je n'arrive pas a trouver le problème...

Est ce que vous pourriez m'éclairer sur mon erreur?


Voici mon code complet :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
 
/**
 *
 * Class test de l'algorithme de remplissage par diffusion
 */
public class AlgoPotDePeinture extends JFrame {
 
    private javax.swing.JLabel labImg;
    private BufferedImage buf;
    private ImageIcon icon;
    private Point pt;
    private Color colorSelect;
    private Ecouteur ecoute;
 
    private javax.swing.JMenuItem JMInouveau;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenuBar jMenuBar2;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
 
    private javax.swing.JPanel panCouleur;
    private ButtonGroup group;
    private javax.swing.JToggleButton jtbBlanc;
    private javax.swing.JToggleButton jtbBleu;
    private javax.swing.JToggleButton jtbCiel;
    private javax.swing.JToggleButton jtbGris;
    private javax.swing.JToggleButton jtbJaune;
    private javax.swing.JToggleButton jtbMarron;
    private javax.swing.JToggleButton jtbNoire;
    private javax.swing.JToggleButton jtbOrange;
    private javax.swing.JToggleButton jtbRose;
    private javax.swing.JToggleButton jtbRouge;
    private javax.swing.JToggleButton jtbVert;
    private javax.swing.JToggleButton jtbViolet;
 
    public AlgoPotDePeinture() {
        initCompo();
        colorSelect = Color.CYAN;
 
    }
 
    public void initCompo() {
 
        setTitle("Pot de Peinture");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        panCouleur = new JPanel(new GridLayout(12,1,5,5));
        jMenuBar2 = new javax.swing.JMenuBar();
        jMenu3 = new javax.swing.JMenu();
        JMInouveau = new javax.swing.JMenuItem();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
 
        jMenu3.setText("File");
 
        JMInouveau.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.ALT_MASK));
        JMInouveau.setText("Nouveau Coloriage");
 
        jMenu3.add(JMInouveau);
 
        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.ALT_MASK));
        jMenuItem1.setText("Quitter");
        jMenu3.add(jMenuItem1);
 
        jMenuBar2.add(jMenu3);
 
        jMenu4.setText("Edit");
 
        jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.ALT_MASK));
        jMenuItem2.setText("Selection Couleurs");
        jMenu4.add(jMenuItem2);
 
        jMenuBar2.add(jMenu4);
 
        setJMenuBar(jMenuBar2);
 
        icon = new javax.swing.ImageIcon(getClass().getResource("1.png")); // image simple d'un dessin a colorier
 
        labImg = new JLabel();
        labImg.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        labImg.setIcon(icon);
 
        ecoute = new Ecouteur();
        group = new ButtonGroup();
        jtbNoire = new javax.swing.JToggleButton();
        jtbBlanc = new javax.swing.JToggleButton();
        jtbBleu = new javax.swing.JToggleButton();
        jtbRouge = new javax.swing.JToggleButton();
        jtbJaune = new javax.swing.JToggleButton();
        jtbVert = new javax.swing.JToggleButton();
        jtbRose = new javax.swing.JToggleButton();
        jtbGris = new javax.swing.JToggleButton();
        jtbViolet = new javax.swing.JToggleButton();
        jtbCiel = new javax.swing.JToggleButton();
        jtbOrange = new javax.swing.JToggleButton();
        jtbMarron = new javax.swing.JToggleButton();
 
        jtbNoire.setBackground(new java.awt.Color(0, 0, 0));
        panCouleur.add(jtbNoire);
        jtbNoire.addActionListener(ecoute);
        jtbNoire.setActionCommand("1");
 
        jtbBlanc.setBackground(new java.awt.Color(255, 255, 255));
        panCouleur.add(jtbBlanc);
        jtbBlanc.addActionListener(ecoute);
        jtbBlanc.setActionCommand("2");
 
        jtbBleu.setBackground(new java.awt.Color(0, 0, 255));
        panCouleur.add(jtbBleu);
        jtbBleu.addActionListener(ecoute);
        jtbBleu.setActionCommand("3");
 
        jtbRouge.setBackground(new java.awt.Color(255, 0, 0));
        panCouleur.add(jtbRouge);
        jtbRouge.addActionListener(ecoute);
        jtbRouge.setActionCommand("4");
 
        jtbJaune.setBackground(new java.awt.Color(255, 255, 0));
        panCouleur.add(jtbJaune);
        jtbJaune.addActionListener(ecoute);
        jtbJaune.setActionCommand("5");
 
        jtbVert.setBackground(new java.awt.Color(0, 204, 0));
        panCouleur.add(jtbVert);
        jtbVert.addActionListener(ecoute);
        jtbVert.setActionCommand("6");
 
        jtbRose.setBackground(new java.awt.Color(255, 153, 255));
        panCouleur.add(jtbRose);
        jtbRose.addActionListener(ecoute);
        jtbRose.setActionCommand("7");
 
        jtbGris.setBackground(new java.awt.Color(153, 153, 153));
        panCouleur.add(jtbGris);
        jtbGris.addActionListener(ecoute);
        jtbGris.setActionCommand("8");
 
        jtbViolet.setBackground(new java.awt.Color(153, 0, 153));
        panCouleur.add(jtbViolet);
        jtbViolet.addActionListener(ecoute);
        jtbViolet.setActionCommand("9");
 
        jtbCiel.setBackground(Color.cyan);
        panCouleur.add(jtbCiel);
        jtbCiel.addActionListener(ecoute);
        jtbCiel.setActionCommand("10");
        jtbNoire.setSelected(true);
 
        jtbOrange.setBackground(new java.awt.Color(255, 153, 51));
        panCouleur.add(jtbOrange);
        jtbOrange.addActionListener(ecoute);
        jtbOrange.setActionCommand("11");
 
        jtbMarron.setBackground(new java.awt.Color(204, 102, 0));
        panCouleur.add(jtbMarron);
        jtbMarron.addActionListener(ecoute);
        jtbMarron.setActionCommand("12");
 
        group.add(jtbNoire);
        group.add(jtbBlanc);
        group.add(jtbBleu);
        group.add(jtbRouge);
        group.add(jtbJaune);
        group.add(jtbVert);
        group.add(jtbRose);
        group.add(jtbGris);
        group.add(jtbViolet);
        group.add(jtbCiel);
        group.add(jtbOrange);
        group.add(jtbMarron);
 
        getContentPane().setBackground(Color.BLACK);
        getContentPane().add(panCouleur,BorderLayout.EAST);
        getContentPane().add(labImg);
        setSize(800,600);
 
        setLocationRelativeTo(null);
        setVisible(true);
 
 
 
        labImg.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
 
                pt = new Point(e.getPoint());			// récupère le point du clic sourie sur dessin
                buf = new BufferedImage(labImg.getWidth(),	// repaint l'image avec la partie colorié sur le labimag
		   labImg.getHeight(),BufferedImage.TYPE_INT_RGB);
                Graphics2D g2d = buf.createGraphics();
                labImg.printAll(g2d);
                g2d.dispose();
 
                floodFill(buf, colorSelect, pt);
 
                labImg.setIcon(new javax.swing.ImageIcon(buf));
 
            }
        });
 
 
 
 
 
    }
 
 
    /**
     * Recupere et return ImageIcon affichee dans le JLabel labImg
     * @param imageName
     * @return icon
     */
    public void setImage(String imageName) {
        icon = new javax.swing.ImageIcon(getClass().getResource(imageName));     
    }
 
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new AlgoPotDePeinture();
            }
        });
    }
 
    /**
* Algorythme de remplissage par diffusion:
* Fills the selected pixel and all surrounding pixels of the same color with the fill color.
* @param img image on which operation is applied
* @param fillColor color to be filled in
* @param loc location at which to start fill
* @throws IllegalArgumentException if loc is out of bounds of the image
*/
public void floodFill(BufferedImage img, Color fillColor, Point loc) {
 
        if (loc.x < 0 || loc.x >= img.getWidth() || loc.y < 0 || loc.y >= img.getHeight()) throw new IllegalArgumentException();
 
        WritableRaster raster = img.getRaster();
        int[] fill =
        new int[] {fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(),
                fillColor.getAlpha()};
        int[] old = raster.getPixel(loc.x, loc.y,  new int[4]);
 
        // Checks trivial case where loc is of the fill color
        if (isEqualRgba(fill, old)) return;
 
        floodLoop(raster, loc.x, loc.y, fill, old);
}
 
// Recursively fills surrounding pixels of the old color
private void floodLoop(WritableRaster raster, int x, int y, int[] fill, int[] old) {
        Rectangle bounds = raster.getBounds();
        int[] aux = {255, 255, 255,old[3] };
 
        // finds the left side, filling along the way
        int fillL = x;
        do {
                raster.setPixel(fillL, y, fill);
                fillL--;
        } while (fillL >= 0 && isEqualRgba(raster.getPixel(fillL, y, aux), old));
        fillL++;
 
        // find the right right side, filling along the way
        int fillR = x;
        do {
                raster.setPixel(fillR, y, fill);
                fillR++;
        } while (fillR < bounds.width - 1 && isEqualRgba(raster.getPixel(fillR, y, aux), old));
        fillR--;
 
        // checks if applicable up or down
        for (int i = fillL; i <= fillR; i++) {
                if (y > 0 && isEqualRgba(raster.getPixel(i, y - 1, aux), old)) floodLoop(raster, i, y - 1,
                fill, old);
                if (y < bounds.height - 1 && isEqualRgba(raster.getPixel(i, y + 1, aux), old)) floodLoop(
                raster, i, y + 1, fill, old);
        }
}
 
// Returns true if RGBA arrays are equivalent, false otherwise
// Could use Arrays.equals(int[], int[]), but this is probably a little faster...
private boolean isEqualRgba(int[] pix1, int[] pix2) {
        return pix1[0] == pix2[0] && pix1[1] == pix2[1] && pix1[2] == pix2[2] && pix1[3] == pix2[3];
}
 
class Ecouteur implements ActionListener {
 
        public void actionPerformed(ActionEvent e) {
            String x = e.getActionCommand();
            if(x.equals("1")==true) colorSelect = jtbNoire.getBackground();
            if(x.equals("2")==true) colorSelect = jtbBlanc.getBackground();
            if(x.equals("3")==true) colorSelect = jtbBleu.getBackground();
            if(x.equals("4")==true) colorSelect = jtbRouge.getBackground();
            if(x.equals("5")==true) colorSelect = jtbJaune.getBackground();
            if(x.equals("6")==true) colorSelect = jtbVert.getBackground();
            if(x.equals("7")==true) colorSelect = jtbRose.getBackground();
            if(x.equals("8")==true) colorSelect = jtbGris.getBackground();
            if(x.equals("9")==true) colorSelect = jtbViolet.getBackground();
            if(x.equals("10")==true) colorSelect = jtbCiel.getBackground();
            if(x.equals("11")==true) colorSelect = jtbOrange.getBackground();
            if(x.equals("12")==true) colorSelect = jtbMarron.getBackground();
        }
 
}
 
}