views:

28

answers:

1

I'm writing a program that will do image processing on a 16 bit tiff image (5 bit red, 6 bit green, 5 bit blue) but unfortunately the code I've written to do so treats the image data as 8 bit.

To elaborate with code, I read the image into memory with ImageIO utility class like so:

BufferedImage image = ImageIO.read(imageFile);

and later on use this loop to retrieve pixel information:

Matrix imageMatrix = new Matrix(image.getHeight(), image.getWidth());
Raster raster = image.getData();
double[] pixelColor = new double[4];
for (int x = 0; x < image.getWidth(); x = x + 1) {
    for (int y = 0; y < image.getHeight(); y = y + 1) {
        raster.getPixel(x, y, pixelColor);
        double pixelColorAverage = (pixelColor[0] + pixelColor[1] + pixelColor[2]) / 3.0;
        imageMatrix.set(y, x, pixelColorAverage);
    }
}
return imageMatrix;

The problem is that raster.getPixel(x, y, pixelColor); returns each RGB value in 8 bits (in my test image, the 0,0 pixel value is returned as 24,24,24 [8 bit values] when it should be 6168,6168,6168 [16 bit values]).

I've tried changing the simplistic ImageIO.read(imageFile) to the following lines of code based on another stack overflow tiff question:

BufferedImage image = ImageIO.read(file);
BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_USHORT_565_RGB);
convertedImage.createGraphics().drawRenderedImage(image, null);

But this time, the raster.getPixel(x, y, pixelColor); returns 3,6,3 which isn't correct either.

Based on the fact that ImageIO has support for tiff images and buffered image has a 5-6-5 style 16 bit image format, I can only assume this is possible, but I'm stumped as to what I'm missing.

+1  A: 

The problem is that raster.getPixel(x, y, pixelColor); returns each RGB value in 8 bits (in my test image, the 0,0 pixel value is returned as 24,24,24 [8 bit values] when it should be 6168,6168,6168 [16 bit values]).

That statement is incorrect.

16 bits per pixel does not mean 16 bits per Red or Green or Blue value. It means 16 bits represents the combined R and G and B values.

So a 16 bit short value can be broken down to represent one pixel.

5 bits represent the Red value. 6 bits represent the Green value. 5 bits represent the Blue value.

Red   Green  Blue
----- ------ -----
10111 101010 11100

Combined you get 1011110101011100 binary or 48476 Decimal.

Never having coded in Java, I would suspect that you would need to use a different function call to get the value you are looking for. Perhaps try [getDataElements][1] to obtain the 16 bit value for the pixel in question.

Rememeber, each pixel is 16 bits. You are confusing that with 24 bit (each pixel is 8 bits) or 32 bit (each pixel is 8 bits plus an 8 bit alpha value.)

This article from MSDN should help you retreive the RGB values from the 16 bit value.

(You will also have to correct your averaging code.)

[1]: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/image/Raster.html#getDataElements(int, int, java.lang.Object)

You're correct. I was definitely confusing the 5-6-5 bits per channel as 16 bits per channel instead of just 16 bits total, and therefore the 3,6,3 RGB value is correct for that color model. Thanks for pointing out the flaw in my conclusions and helping me fix my code.
Peter Nix