Reputation: 12141
I know its possible to convert an image to CS_GRAY using
public static BufferedImage getGrayBufferedImage(BufferedImage image) {
BufferedImageOp op = new ColorConvertOp(ColorSpace
.getInstance(ColorSpace.CS_GRAY), null);
BufferedImage sourceImgGray = op.filter(image, null);
return sourceImgGray;
}
however, this is a chokepoint of my entire program. I need to do this often, on 800x600 pixel images and takes about 200-300ms for this operation to complete, on average. I know I can do this alot faster by using one for loop to loop through the image data and set it right away. The code above on the other hand constructs a brand new 800x600 BufferedImage that is gray scale. I would rather just transform the image I pass in.
Does any one know how to do this with a for loop and given that the image is RGB color space?
Upvotes: 2
Views: 3494
Reputation: 10786
private static int grayscale(int rgb) {
int r = rgb >> 16 & 0xff;
int g = rgb >> 8 & 0xff;
int b = rgb & 0xff;
int cmax = Math.max(Math.max(r, g),b);
return (rgb & 0xFF000000) | (cmax << 16) | (cmax << 8) | cmax;
}
public static BufferedImage grayscale(BufferedImage bi) {
BufferedImage bout = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB);
int[] rgbArray = new int[bi.getWidth() * bi.getHeight()];
rgbArray = bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), rgbArray, 0, bi.getWidth());
for (int i = 0, q = rgbArray.length; i < q; i++) {
rgbArray[i] = grayscale(rgbArray[i]);
}
bout.setRGB(0, 0, bout.getWidth(), bout.getHeight(), rgbArray, 0, bout.getWidth());
return bout;
}
Whatever you're doing you are likely doing something wrong. You shouldn't be regenerating a buffered image over and over again. But, rather figuring out a scheme to simply update the buffered image, or take the original pixels from the original and just using the grayscale which is the max of the RGB components, in each of the sections.
Upvotes: 1
Reputation: 2798
ColorConvertOp.filter
takes two parameters. The second parameter is also a BufferedImage
, which will be the destination. If you pass a correct BufferedImage
to the filter
method it saves you from the hassle to create a fresh BufferedImage
.
Upvotes: 3