0

I have raw grayscale image pixels represented by short[]. I would like to create BufferedImage from it and save it as PNG. Since there is no TYPE_SHORT_GRAY defined for BufferedImage I'm creating one myself this way:

short[] myRawImageData;

// Create signed 16 bit data buffer, and compatible sample model
DataBuffer dataBuffer = new DataBufferShort(myRawImageData, w * h);
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_SHORT, w, h, 1, w, new int[] {0});

// Create a raster from sample model and data buffer
WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);

// Create a 16 bit signed gray color model
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorModel colorModel = new ComponentColorModel(colorSpace, false, false, Transparency.OPAQUE, DataBuffer.TYPE_SHORT);

// Finally create the signed 16 bit image
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);

try (FileOutputStream fos = new FileOutputStream("/tmp/tst.png")) {
    ImageIO.write(image, "png", fos);// <--- Here goes the exception
} catch (Exception ex) { 
    ex.printStackTrace();
}

So far so good but when I'm trying to use ImageIO.write to save it as PNG I'm getting ArrayIndexOutOfBoundsException.

JobNick
  • 473
  • 1
  • 6
  • 18
  • You should a) post the code that demonstrates your problem as a [MCVE] and b) describe what happens, what you expect to happen, how they differ and the specific errors you are encountering. – pvg May 28 '17 at 06:14

1 Answers1

0

Your code works fine for me, the only way I got your error was when I changed the bandOffsets. Could you give us more of your code?

EDIT If you have negative data in your dataset, you should probably be using ushort instead of short.

    int h = 64, w = 64;
    short[] myRawImageData = new short[4096];
    for (int i = 0; i < 4096; i++){
        //this rolls over into negative numbers
        myRawImageData[i] = (short) (i * 14);
    }

    // Create signed 16 bit data buffer, and compatible sample model
    DataBuffer dataBuffer = new DataBufferUShort(myRawImageData, w * h);
    SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_USHORT, w, h, 1, w, new int[] {0});

    // Create a raster from sample model and data buffer
    WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);

    // Create a 16 bit signed gray color model
    ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ColorModel colorModel = new ComponentColorModel(colorSpace, false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);

    // Finally create the signed 16 bit image
    BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);

    try (FileOutputStream fos = new FileOutputStream("/tmp/tst.png")) {
        ImageIO.write(image, "png", fos);// <--- Here goes the exception
    } catch (Exception ex) {
        ex.printStackTrace();
    }

This is assuming you expect negative values to be the brighter half of the gamut.

Kyle Berezin
  • 597
  • 4
  • 20
  • Still works great for me, perhaps your input data is the issue. – Kyle Berezin May 28 '17 at 07:29
  • My input data contains negative numbers. Does your also ? – JobNick May 28 '17 at 07:33
  • 1
    Perhaps you should just treat it as a ushort. A negative value doesn't really map to a color, and if you want that last bit of data, let the program know. So `DataBuffer.TYPE_USHORT` may be your answer. – Kyle Berezin May 28 '17 at 07:50
  • I've ended shifting values from `short` to `ushort` by adding 2^15 and then creating `BufferedImage` with `TYPE_USHORT_GRAY` type. Now everything works – JobNick May 28 '17 at 08:43