java.awt.image.BufferedImage 24-bit RGB to 8-bit Grayscale conversion using custom ColorSpace

mmm picture mmm · Oct 13, 2010 · Viewed 17.1k times · Source

I want to do a simple color to grayscale conversion using java.awt.image.BufferedImage. I'm a beginner in the field of image processing, so please forgive if I confused something.

My input image is an RGB 24-bit image (no alpha), I'd like to obtain a 8-bit grayscale BufferedImage on the output, which means I have a class like this (details omitted for clarity):

public class GrayscaleFilter {
    private BufferedImage colorFrame;
    private BufferedImage grayFrame = 
        new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

I've succesfully tried out 2 conversion methods until now, first being:

    private BufferedImageOp grayscaleConv = 
        new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);

    protected void filter() {
        grayscaleConv.filter(colorFrame, grayFrame);
    }

And the second being:

    protected void filter() {       
        WritableRaster raster = grayFrame.getRaster();

        for(int x = 0; x < raster.getWidth(); x++) {
            for(int y = 0; y < raster.getHeight(); y++){
                int argb = colorFrame.getRGB(x,y);
                int r = (argb >> 16) & 0xff;
                int g = (argb >>  8) & 0xff;
                int b = (argb      ) & 0xff;

                int l = (int) (.299 * r + .587 * g + .114 * b);
                raster.setSample(x, y, 0, l);
            }
        }
    }

The first method works much faster but the image produced is very dark, which means I'm losing bandwidth which is unacceptable (there is some color conversion mapping used between grayscale and sRGB ColorModel called tosRGB8LUT which doesn't work well for me, as far as I can tell but I'm not sure, I just suppose those values are used). The second method works slower, but the effect is very nice.

Is there a method of combining those two, eg. using a custom indexed ColorSpace for ColorConvertOp? If yes, could you please give me an example?

Thanks in advance.

Answer

Sorter picture Sorter · Oct 18, 2012
public BufferedImage getGrayScale(BufferedImage inputImage){
    BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
    Graphics g = img.getGraphics();
    g.drawImage(inputImage, 0, 0, null);
    g.dispose();
    return img;
}