Skip to main content

Decoding JPG to BufferedImage TYPE_BYTE_GRAY

5 replies [Last post]
ifoster
Offline
Joined: 2006-03-28

I am seeking some assistance in using the ImageIO API to read raw byte[] JPG images to the specific TYPE_BYTE_GRAY BufferedImage. The JPG source files are 8 bit grayscale images.

If I use the createImage (byte[] rawImageData, int imageoffset, int imagelength) in the java.awt.Toolkit, I get a perfectly good image 8 bit gray scale image, but not a BufferedImage.

If I use the ImageIO.read(new ByteArrayInputStream ( rawImageData )) I get an image BufferedImage but the souce image is now an TYPE_USHORT_GRAY.

I have tried to use the ImageReadParam class and set the destination image to a BufferedImage.TYPE_BYTE_GRAY as follows;

ImageInputStream stream = ImageIO.createImageInputStream( new ByteArrayInputStream(pImage));
ImageReader reader = (ImageReader) iter.next();
ImageReadParam param = reader.getDefaultReadParam();
image = new BufferedImage(640, 480, BufferedImage.TYPE_BYTE_GRAY);
param.setDestination((BufferedImage) image);
reader.setInput(stream, true, true);
image = reader.read(0, param);
stream.close();
reader.dispose();

The image returned is a BufferedImage and appears to be BufferedImage.TYPE_BYTE_GRAY, however, all the pixels are zero. I feel I must be missing something simple but I just am unable to crack it. Any pointers offered will be much appreciated.

I am using Java Version 1.5.0_22-b03 on a Windows XP operating system.

ifoster

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Harald Kuhr

Hi again Ian,

On 13. mai 2010, at 02.26, jai-imageio@javadesktop.org wrote:

> After much scratching around, I have found that it is the ColorModel that is causing the problems. The JPG reader returns a BufferedImage with an IndexedColorModel (which is what I actually asked for by spcifying TYPE_BYTE_GRAY) but the for image processing purposes I need a DirectColorModel.

From the API doc for BufferedImage#TYPE_BYTE_GRAY: "Represents a unsigned byte grayscale image, non-indexed. This image has a ComponentColorModel with a CS_GRAY ColorSpace."

So if you get anything else from ImageIO, that is a bug.

A ComponentColorModel is of course still not a DirectColorModel though, so it might not help you much.. :-/

> It appears that the ImageIO JPG reader is not compatible with DirectColorModels so I am stuck between a rock and a hard place.
> At this point I think I have two options; continue using the awt.Toolkit to read the images, or build in support for IndexedColorModels in my image processor. I feel the second option is best, it is a bit of work in the short term but should payoff dividends into the future.

I guess you have some really hard memory contraints, or your images are huge? Otherwise it would be trivial to create a new BufferedImage of the correct type (with DirectColorModel), paint your image onto it, discard the original and go on with the processing..

Also, any color model has methods for converting raw pixel values to int RGB (although some slower than others), so it should be possible to support non-DCM with a generic fallback. But as you say, it's a bit more work..

Good luck,

--
Harald K
[att1.html]

ifoster
Offline
Joined: 2006-03-28

Hi Harald,

> From the API doc for BufferedImage#TYPE_BYTE_GRAY:
> "Represents a unsigned byte grayscale image,
> non-indexed. This image has a ComponentColorModel
> with a CS_GRAY ColorSpace."
> So if you get anything else from ImageIO, that is a
> bug.
>
> A ComponentColorModel is of course still not a
> DirectColorModel though, so it might not help you
> much.. :-/

Sorry, of course you are right, BufferedImage.TYPE_BYTE_GRAY has a ComponentColorModel not an IndexedColorModel, but as you say ComponentColorModel is still not DirectColorModel.

My constraints is not strickly speaking memory but speed (although I am not sure if the two issues can truely be considered as seperate!), I am processing and displaying hundreds of thousands of images so that any steps in the process that are not absolutely necessary I want to eliminate.

Somebody has recommended looking at the US NIH ImageJ image processing library, it has built in support for BufferedIMages. I will do some performance profiling to see if I can get acceptable throughput and processing results.

Best regards,

Ian

Harald Kuhr

Hi ifoster,

On 7. mai 2010, at 09.27, jai-imageio@javadesktop.org wrote:

> I am seeking some assistance in using the ImageIO API to read raw byte[] JPG images to the specific TYPE_BYTE_GRAY BufferedImage. The JPG source files are 8 bit grayscale images.
>
> If I use the createImage (byte[] rawImageData, int imageoffset, int imagelength) in the java.awt.Toolkit, I get a perfectly good image 8 bit gray scale image, but not a BufferedImage.

Maybe not what you are looking for, but I have implemented a fairly straight-forward conversion from Image to BufferedImage:

http://github.com/haraldk/TwelveMonkeys/blob/master/common/common-image/...

(latest binary can be downloaded here: http://download.java.net/maven/2/com/twelvemonkeys/twelvemonkeys-core/2....)

> If I use the ImageIO.read(new ByteArrayInputStream ( rawImageData )) I get an image BufferedImage but the souce image is now an TYPE_USHORT_GRAY.

Another way is of course to create a BufferedImage of TYPE_BYTE_GRAY and paint the TYPE_USHORT_GRAY into it. A waste of time and memory of course, but you get the result you want.

> I have tried to use the ImageReadParam class and set the destination image to a BufferedImage.TYPE_BYTE_GRAY as follows;
>
[...]
>
> The image returned is a BufferedImage and appears to be BufferedImage.TYPE_BYTE_GRAY, however, all the pixels are zero. I feel I must be missing something simple but I just am unable to crack it. Any pointers offered will be much appreciated.

I have always felt this part of the API a little under-specified (or maybe just not understood), as some ImageReaders are known to have a mismatch between what ImageReader.html#getImageTypes(int) returns and what is really supported in the deoding process..

Does the JPEG ImageReader return an ImageTypeSpecifier that conforms to TYPE_BYTE_GRAY? If so, it should be supported, and your described behaviour is a bug. If not, then the described behaviour is probably still a bug, but not really unexpected... :-/

Also note that the image returned from the read-method should always be the same instance as the one you passed to param.setDestination().

You might try to see if param.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(TYPE_BYTE_GRAY) instead of param.setDestination makes a difference (it shouldn't, but you never know).

Best regards,

--
Harald K

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

ifoster
Offline
Joined: 2006-03-28

Hi Harald,

Thanks for your input, it put me on the track to find the cause of my problems.

After much scratching around, I have found that it is the ColorModel that is causing the problems. The JPG reader returns a BufferedImage with an IndexedColorModel (which is what I actually asked for by spcifying TYPE_BYTE_GRAY) but the for image processing purposes I need a DirectColorModel. It appears that the ImageIO JPG reader is not compatible with DirectColorModels so I am stuck between a rock and a hard place.

At this point I think I have two options; continue using the awt.Toolkit to read the images, or build in support for IndexedColorModels in my image processor. I feel the second option is best, it is a bit of work in the short term but should payoff dividends into the future.

Thanks again for the pointers.

Ian

demonduck
Offline
Joined: 2008-03-14

Just an idea but you could make an int array with the r, g, b values corresponding to the colors in the indexed color image and then just setRGB() in a BufferedImage of the appropriate size.

Or just set the r, g, b values in a blank BufferedImage of the same size and with a DirectColorModel. You can loop through that process pretty fast.

Not real convenient but it would let you get away from the Toolkit.

Over all you might be more efficient computationally.