2

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.

10
  • Because I'm lazy, and it's way to easy to screw up, I prefer to use Color(int, boolean) to convert a packed int into a Color object, then I can use getRed/Green/Blue to get the individual colors, you could then use something like new Color(pixel.getRed(), 0, 0).getRGB() to create packed int value for the specific color. In my "quick" test, this worked fine Commented Jun 19, 2015 at 4:12
  • BufferedImage.TYPE_BYTE_GRAY also looks wrong, it probably should be BufferedImage.TYPE_INT_RGB. Commented Jun 19, 2015 at 4:14
  • I'd also say, after some more testing, that your int conversion seems fine ;) Commented Jun 19, 2015 at 4:15
  • "When I changed the type of the bufferedImage for the red one to GRAY (LINE 4)" And what do you except? Commented Jun 19, 2015 at 4:19
  • I expect an 8 bits per pixel image. However, the generated images looks gray not pure red. Commented Jun 19, 2015 at 6:30

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for you suggestions. The problem is I need a BufferedImage contains 8 bits/pixel and this 8 bits represent a color (eg. red) not a gray color. For your first suggestion, each color will be represented based on gray color which is unacceptable. For the second choice, the image depth is 24, I need it 8. I did't understand your third option.
If something seems impossible to achieve, you are likely approaching the problem the wrong way. ;-) An 8 bit gray value is just a number between 0 and 255. It can perfectly fine be used to represent a red value (even though it will by default display as gray). The third option allows you get 256 shades of either red, green or blue, using a palette. The values in the raster will be exactly the same as the grayscale one. And you will have to change the file format to PNG, GIF or BMP. JPEG can't store this.
The problem from the begging, I want to evaluate video quality using a matrix called Multi-scale structural similarity, I have a java code for this. However, this code support 8, 16, and 32 bits images. So, to be able to use this matrix, I need to convert the RGB 24 bits into either RGB 32 bits or divide the RGB image into three R, G, B images and apply the matrix between these individual ones. This is the matrix implementation: rsb.info.nih.gov/ij/plugins/download/MS_SSIM_index.java. when I tried to convert the 24GRB image into 32GRB, ImagePlus still gives me 24bits as pixel depth.
According to the docs, the plugin you linked supports 8, 16 or 32 bits gray only.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.