I'm writing a method that will attempt to find a color in a bufferedImage. At the moment, the method works by taking a screencap, and then scanning the image for a specific color. Now I'd like to add some RGB tolerence, so if the user is trying to find color (1, 3, 5) with tolerance 1, any color +-1 R, B or G will return true.
I could solve this by first generating a arrayList of RGB values that work, and then for each pixel I could go through the array and check with each value. The problem is that would probably get VERY slow for high tolerances on large images.
Is there a more efficient or possibly a built in way I can do this? Here is my method as it stands right now. Thank you!
public static Point findColor(Box searchArea, int color){
System.out.println("Test");
BufferedImage image = generateScreenCap(searchArea);
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
if((image.getRGB(i, j)*-1)==color){
return new Point(i + searchArea.x1, j + searchArea.y1);
}
}
}
return new Point(-1, -1);
}
Edit: I'm using the int RGB values for all comparisons, so instead of Color[1, 1, 1], I use Color.getRGB() which returns a negative int which I convert to positive for end user simplicity.
You need to compare RGB values and not the "whole" color if you want to have a custom tolerance. Here is the code, it is not tested, but you get the idea :
public static Point findColor(Box searchArea, int r, int g, int b, int tolerance) {
// Pre-calc RGB "tolerance" values out of the loop (min is 0 and max is 255)
int minR = Math.max(r - tolerance, 0);
int minG = Math.max(g - tolerance, 0);
int minB = Math.max(b - tolerance, 0);
int maxR = Math.min(r + tolerance, 255);
int maxG = Math.min(g + tolerance, 255);
int maxB = Math.min(b + tolerance, 255);
BufferedImage image = generateScreenCap(searchArea);
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
// get single RGB pixel
int color = image.getRGB(i, j);
// get individual RGB values of that pixel
// (could use Java's Color class but this is probably a little faster)
int red = (color >> 16) & 0x000000FF;
int green = (color >> 8) & 0x000000FF;
int blue = (color) & 0x000000FF;
if ( (red >= minR && red <= maxR) &&
(green >= minG && green <= maxG) &&
(blue >= minB && blue <= maxB) )
return new Point(i + searchArea.x1, j + searchArea.y1);
}
}
return new Point(-1, -1);
}