How do I retrieve 16 bit pixel data from a tiff in Java?
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 correc开发者_C百科t 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.
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)
精彩评论