This Java tutorial shows how to convert a color image to a gray scale image in Java. In Java, there are a number of ways to convert a color image to gray scale. This tutorial will show you three ways convert the image including output quality and performance.
For reference, below is the color image that was converted:
Changing the Color Space
One way to convert a color image to gray scale, is to change the color space of the image. The sample code below shows how to change the color space:
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
BufferedImage image = op.filter(bufferedImage, null);
Performance: Poor (approx. 60ms)
Image Results: Poor
Drawing to a Grayscale BufferedImage
The easiest way to convert a color image to a gray scale image is to simply draw the color image to a gray scale BufferedImage. The sample code below shows how to draw the colored image to a gray scale BufferedImage:
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_BYTE_GRAY);
Graphics g = image.getGraphics();
g.drawImage(colorImage, 0, 0, null);
g.dispose();
Performance: Good (approx. 9 ms)
Image Results: Best
Using the GrayFilter
The final way to convert a color image to a gray scale image is to use the GrayFilter. In order to use the GrayFilter, the color image must either be an ImageProducer or a BufferedImage (use the getSource() method to get the ImageProducer). The sample code below shows how to use the GrayFilter:
ImageFilter filter = new GrayFilter(true, 50);
ImageProducer producer = new FilteredImageSource(colorImage.getSource(), filter);
Image mage = this.createImage(producer);
Performance: Best (approx. 1 ms)
Image Results: Good. When constructing the GrayFilter, you can control the brightness of the grays with the second parameter.
Which Method Should You Use
The low quality and slow performance, should rule out using the ColorSpace method. If you need the best performance and can live with the image quality, the GrayFilter would be the option for you. Drawing to a gray scale BufferedImage is the overall best option, it is only a few milliseconds slower than the best, the image quality is the best, and the code is the simplest.

11 comments:
Nice article, just what I wanted.
You didn't include all the implementation notes and stuff. simple, yet very effective.
Thank you again.
how to implement the code?..can u give me full code example of it.. i really blur about this...i take a snapshot using
byte[] image = videoControl.getSnapshot("encoding=jpeg")
i hope u can help me..thanks..
Hey dude.. the code was inofrmative.. But cn u gimme where to implement it??? V r working on a title hw to convert JPEG images to PGM....
//import java.io.*;
import javax.media.jai.*;
import javax.imageio.ImageIO;
public class ConvertSpeed
{
private static String inputFileName = "C:\\Program Files\\balloon.jpg";
private static String outputFileName = "C:\\Program Files\\balloon.pgm";
public static void main(String args[])
{
System.out.println("Start....");
File inputFile = new File(inputFileName);
RenderedOp src = JAI.create("fileload", inputFile.getAbsolutePath());
FileOutputStream stream = null;
try
{
stream = new FileOutputStream(outputFileName);
ImageIO.write(src, "pgm", stream);
}
catch(IOException ioe)
{
System.out.println(ioe);
}
System.out.println("Done.");
}
}//
This s our code.. it compiles well but shows me error at 15th line whil running!!!
Cn u ping me back at kehakartik@gmail.com
Thnks!!!
Extremely informative article, well researched and clearly presented. I am thankful Gizmo took the time to share this informative post.
I think you forgot to mention the memory overhead for transformation #2 and #3 (additional ImageBuffer in memory)...
transformation #1 should be less memory consuming than the others.
regards
Very helpful example, but I get different performance results with method 1 and 2. Method 1 took me 47 ms and method 2 took 78 ms to transform one 580x580 color image to grayscale.
Thanks for sharing!
Thanks for sharing! I'd like to use #2, however transparency is lost :(.
In hope for everything to be useful, here is the code that creates new instance of grayscale transparent image:
ColorSpace gsColorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ComponentColorModel ccm = new ComponentColorModel(gsColorSpace, true, false,
Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
WritableRaster raster = ccm.createCompatibleWritableRaster(width, height);
Image result = new BufferedImage(ccm, raster, ccm.isAlphaPremultiplied(), null);
When using JAI, a BandCombine operation that calculates the luminance gives off a great gray scale image at decent speed.
PlanarImage gray = JAI.create("bandcombine",image,new double[][] { 0.299, 0.587, 0.114, 0.0 } });
@Anonymous(April 27, 2010 6:03 PM)
Oh wow, thanks so much for that transparent grayscale code. It's a real life saver when making 'disabled' icons.
Post a Comment