ldog
ldog

Reputation: 12141

Java Convert ColorSpace of BufferedImage to CS_GRAY without using ConvertColorOp

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

Answers (2)

Tatarize
Tatarize

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

ablaeul
ablaeul

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

Related Questions