You have to read every pixel anyhow. You can do this with
int rgb = bufferedImage.getRGB(x,y);
Alternatively, you can obtain the data buffer from the image and directly obtain the pixels as an int[]
array (as described in the comments), but note that this may have some impact on the performance when rendering this image afterwards.
The next step would be to detect whether the pixel has a certain color. When it comes to photos, a comparison like
if (rgb == Color.BLUE.getRGB()) { ... }
does not make sense: The pixels will not be perfectly blue in most cases. Instead, you could analyze the hue of the RGB value, by converting it into the HSB color space. So you could do something like
float hsb[] = new float[3];
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = (rgb ) & 0xFF;
Color.RGBtoHSB(r, g, b, hsb);
Then the hsb
array will contain the hue, saturation and brightness of the color. These will be values between 0 and 1. The hue multiplied with 360 will give you the "tone" of the color:
The saturation and brightness can be used to detect pixels that are "nearly black" or "nearly white". So your final analysis could roughly (!) look like this:
if (hsb[1] < 0.1 && hsb[2] > 0.9) nearlyWhite();
else if (hsb[2] < 0.1) nearlyBlack();
else {
float deg = hsb[0]*360;
if (deg >= 0 && deg < 30) red();
else if (deg >= 30 && deg < 90) yellow();
else if (deg >= 90 && deg < 150) green();
else if (deg >= 150 && deg < 210) cyan();
else if (deg >= 210 && deg < 270) blue();
else if (deg >= 270 && deg < 330) magenta();
else red();
}
These nested if-statements could also be avoided by using a NavigableMap
and its floorEntry
and ceilingEntry
methods, but the if-statements are probably easier to understand here.