Implementing a "Paint Can"-type tool
-
Hey guys! So I've been trying to get this utility method to work for a while and can't seem to stop overloading the stack. The method should be able to emulate the Paint Can Tool in MS Paint. It takes a BufferedImage, the x- and y-coordinates of the point to apply the method to, and the color with which to paint the area. My implementation is a recursive one, and I know this is the reason for the overflow, but I haven't done any complex recursive method writing as of yet and don't know how I can fix my problem. Here is the code I've written:
static void paintCan(BufferedImage image, int x, int y, Color color) {
int[][] array = new int[image.getWidth()][image.getHeight()];for (int r = 0; r < image.getHeight(); r++) for (int c = 0; c < image.getWidth(); c++) array\[c\]\[r\] = image.getRGB(c, r); changeColor(array, x, y, array\[x\]\[y\], color.getRGB()); for (int r = 0; r < image.getHeight(); r++) for (int c = 0; c < image.getWidth(); c++) image.setRGB(c, r, array\[c\]\[r\]);
}
static void changeColor(int[][] image, int x, int y, int from, int to) {
if (image[x][y] == from) {
image[x][y] = to;int left = x - 1; int right = x + 1; int up = y - 1; int down= y + 1; if (left >= 0) changeColor(image, left, y, from, to); if (right < image.length) changeColor(image, right, y, from, to); if (up >= 0) changeColor(image, x, up, from, to); if (down < image\[0\].length) changeColor(image, x, down, from, to); }
}
This method works perfectly for smaller areas, but when the area selected at the (x, y) point requires too much recursion, a runtime error is thrown. Does anyone know how I can get the method to use less memory and not overload the stack? Help is very appreciated :) Thank you! -max
-
Hey guys! So I've been trying to get this utility method to work for a while and can't seem to stop overloading the stack. The method should be able to emulate the Paint Can Tool in MS Paint. It takes a BufferedImage, the x- and y-coordinates of the point to apply the method to, and the color with which to paint the area. My implementation is a recursive one, and I know this is the reason for the overflow, but I haven't done any complex recursive method writing as of yet and don't know how I can fix my problem. Here is the code I've written:
static void paintCan(BufferedImage image, int x, int y, Color color) {
int[][] array = new int[image.getWidth()][image.getHeight()];for (int r = 0; r < image.getHeight(); r++) for (int c = 0; c < image.getWidth(); c++) array\[c\]\[r\] = image.getRGB(c, r); changeColor(array, x, y, array\[x\]\[y\], color.getRGB()); for (int r = 0; r < image.getHeight(); r++) for (int c = 0; c < image.getWidth(); c++) image.setRGB(c, r, array\[c\]\[r\]);
}
static void changeColor(int[][] image, int x, int y, int from, int to) {
if (image[x][y] == from) {
image[x][y] = to;int left = x - 1; int right = x + 1; int up = y - 1; int down= y + 1; if (left >= 0) changeColor(image, left, y, from, to); if (right < image.length) changeColor(image, right, y, from, to); if (up >= 0) changeColor(image, x, up, from, to); if (down < image\[0\].length) changeColor(image, x, down, from, to); }
}
This method works perfectly for smaller areas, but when the area selected at the (x, y) point requires too much recursion, a runtime error is thrown. Does anyone know how I can get the method to use less memory and not overload the stack? Help is very appreciated :) Thank you! -max
I did some testing with your code and here are my results: 1. Image size does not effect result. 2. The Pixels in your image cause the stack overflow. - When your image is mono colored. - When your image contain n colors in shapes lets say black square, green circle etc... The above throw the Exception - When approximately all pixels of the image vary then your code works fine with any size even with 1920 x 1080. If you want to use the bucket feature in MS Paint here is a simpler way:
BufferedImage image = ImageIO.read(new File("Desert.jpg")); // image from sample images in Win 7 RC
Color c = Color.red;
int x0 = 10,x1 = 100,y0 = 10,y1 = 100;
for (int i = x0; i < x1; i++)
{
for (int j = y0; j < y1; j++)
{
image.setRGB(i, j, c.getRGB());
}
}
ImageIO.write(image, "jpg", new File("Result.jpg"));By the way the recursion problem is in the change color method. Hope this help
-
I did some testing with your code and here are my results: 1. Image size does not effect result. 2. The Pixels in your image cause the stack overflow. - When your image is mono colored. - When your image contain n colors in shapes lets say black square, green circle etc... The above throw the Exception - When approximately all pixels of the image vary then your code works fine with any size even with 1920 x 1080. If you want to use the bucket feature in MS Paint here is a simpler way:
BufferedImage image = ImageIO.read(new File("Desert.jpg")); // image from sample images in Win 7 RC
Color c = Color.red;
int x0 = 10,x1 = 100,y0 = 10,y1 = 100;
for (int i = x0; i < x1; i++)
{
for (int j = y0; j < y1; j++)
{
image.setRGB(i, j, c.getRGB());
}
}
ImageIO.write(image, "jpg", new File("Result.jpg"));By the way the recursion problem is in the change color method. Hope this help
I was aware that it was not the image size, but the number of pixels in the shape being filled that was the problem, and that the recursion overflow error was occurring in the
changeColor()
method... Your solution does not implement the bucket feature in MS Paint, because when you use the paint bucket in Paint it fills all adjacent pixels of a similar color with the color of your choice, what you have given me only fills a rectangle with a certain color :/ Thanks for the reply though! -
I was aware that it was not the image size, but the number of pixels in the shape being filled that was the problem, and that the recursion overflow error was occurring in the
changeColor()
method... Your solution does not implement the bucket feature in MS Paint, because when you use the paint bucket in Paint it fills all adjacent pixels of a similar color with the color of your choice, what you have given me only fills a rectangle with a certain color :/ Thanks for the reply though!I think I found the answer guys. My main problem for looking for help with my problem was that I didn't know what the "paint can tool" functionality was called! But it turns out there is something called the Flood Fill Algorithm that is exactly what I'm talking about implementing. http://en.wikipedia.org/wiki/Flood_fill[^]
-
I think I found the answer guys. My main problem for looking for help with my problem was that I didn't know what the "paint can tool" functionality was called! But it turns out there is something called the Flood Fill Algorithm that is exactly what I'm talking about implementing. http://en.wikipedia.org/wiki/Flood_fill[^]
My bad, in my way I was trying to say that if you give the coordinates of the pixels then use the graphics class to fill in the color but its not practical any way here is a nice implementation of the specified algorithm: http://www.cis.upenn.edu/~matuszek/cit594-2005/ Check FloodFillApplet.java and ColorArrayComponent.java Good luck
-
My bad, in my way I was trying to say that if you give the coordinates of the pixels then use the graphics class to fill in the color but its not practical any way here is a nice implementation of the specified algorithm: http://www.cis.upenn.edu/~matuszek/cit594-2005/ Check FloodFillApplet.java and ColorArrayComponent.java Good luck
Hi ! I think you should use the floodfill algorithms using stack or quee (without a recursive menthod). Because wehn use any recursive menthod it eat alot of memorry and the _stack is limit or very small for your code to execute. This is the link. http://hughm.cs.ukzn.ac.za/~murrellh/ds/code/floodfill/Stacks_and_Queues.html[^] Hope this helpul ! Regards !