Java BufferedImage

1.7k views Asked by At

I have stored a RGB image in a BufferedImage, what I want to do is take each color (eg. red) and store it in a new BufferedImage. So at the end, I will have four BufferedImage, the original one and one for each color. Each BufferedImage for each color should be 8 bits per pixel and this 8 bits contain the color value.

This is what I did.

 String fileName = "test.jpg";
 File inFile = new File(fileName);
 BufferedImage refImg = ImageIO.read(inFile);

 BufferedImage redImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), BufferedImage.TYPE_BYTE_GRAY); // LINE 4
 BufferedImage greenImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), refImg.getType());
 BufferedImage blueImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), refImg.getType());

 for (int i = 0; i < refImg.getWidth(); i++)
   for (int j = 0; j < refImg.getHeight(); j++)
   {
     int rgb = refImg.getRGB(i, j);
     int red = (rgb >> 16) & 0xFF;
     int green = (rgb >> 8) & 0xFF;
     int blue = rgb & 0xFF;

     int ronly = (red << 16) | (0 << 8) | 0;
     int gonly = (0 << 16) | (green << 8) | 0;
     int bonly = (0 << 16) | (0 << 8) | blue;

     redImage.setRGB(i, j, ronly);
     greenImage.setRGB(i, j, gonly);
     blueImage.setRGB(i, j, bonly);
   }

 File redOut = new File("testRed.jpg");
 File greenOut = new File("testGreen.jpg");
 File blueOut = new File("testBlue.jpg");

 ImageIO.write(redImage, "jpg", redOut);
 ImageIO.write(greenImage, "jpg", greenOut);
 ImageIO.write(blueImage, "jpg", blueOut);

However, I am still in the RGB color model. When I changed the type of the bufferedImage for the red one to GRAY (LINE 4), I do not get the red component.

Any help or direction.

1

There are 1 answers

4
Harald K On

It's a bit hard to understand what you are trying to achieve here... If you make the images TYPE_BYTE_GRAY, they will be gray.

Also, if you want to store as JPEG, you have to choose between single channel gray or 3 channel RGB. You can't have single channel red/green/blue.

So, you basically have two options:

In addition to the original RGB image, you could have 3 gray images, stored as grayscale JPEGs. You will need to change some code:

BufferedImage redImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage greenImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage blueImage = new BufferedImage(refImg.getWidth(), refImg.getHeight(), BufferedImage.TYPE_BYTE_GRAY);

...

int ronly = (red   << 16) | (red   << 8) | red;
int gonly = (green << 16) | (green << 8) | green;
int bonly = (blue  << 16) | (blue  << 8) | blue;

redImage.setRGB(i, j, ronly);
greenImage.setRGB(i, j, gonly);
blueImage.setRGB(i, j, bonly);

These images will contain the red, green and blue channels respectively, but they will by default display as gray. You can use LookupOp to convert your images back to all-red/green/blue RGB for display purposes, if needed.

The alternative is to have 3 RGB images containing only red, green and blue (like your initial attempt). These images will be RGB, have 3 channels and store as RGB (as YCbCr, most likely) JPEGs.


A third option would be to use an all-red/green/blue (256 shades) palette IndexColorModel. But JPEG can't store palette/indexed images, so they will have to be converted back to RGB, or you can change the file format to PNG, GIF or BMP.