javaimagebufferedimage16-bit

Write to 16 bit BufferedImage TYPE_USHORT_GRAY


I'm trying to write 16 bit grayscale imagedata to a png using BufferedImage.TYPE_USHORT_GRAY. Normally I write to an image like so:

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

then:

image.setRGB(x,y,Color.getRGB);

to set the pixels, and finally:

ImageIO.write(image, "png", new File(path + ".png"));

to write to a png image.

But now I have this as image:

BufferedImage imageGray = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);

How do I go about saving pixels to that format? Using setRGB() with a 16 bit integer doesn't seem to work, when I open the saved png file I see a lot of banding happening.

I tried saving a simple gradient from 0 to 65535 and then using the setRGB() on the grayscale image, and checked the results in Photoshop. I can see the image consists of smaller gradients every 256 rows. I'm guessing either setRGB() or imageIO doesn't work as I would like it to.

Are there workarounds for this? Does imageIO even support the BufferedImage.TYPE_USHORT_GRAY format? Or can it only save 8 bit data? And if it can save 16bit data, how would I go about saving pixel data, preferably in a way like setRGB() works (so for a certain x,y coordinate)?


Solution

  • As pst already commented below my question:

    Try using the Raster directly?

    Accessing the Raster directly solved the problem :

    BufferedImage bi = BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY)
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            Short s = shortData[x][y]
            bi.getRaster().setDataElements(x, y, Short[] {s})
        }
    }