The problem here is that setRGB()
wants an 0xRRGGBB color value. BufferedImage likes to pretend that the image is RGB, no matter what the data is stored as. You can actually get at the internal DataBufferShort
(with getTile(0, 0).getDataBuffer()
), but it can be tricky to figure out how it is laid out.
If you already have your pixels in a short[]
, a simpler solution might be to copy them into an int[]
instead an jam it into a MemoryImageSource
:
int[] buffer = /* pixels */;
ColorModel model = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] { 16 },
false, true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
Image image = Toolkit.getDefaultToolkit().createImage(
new MemoryImageSource(VERTICAL_PIXELS, HORIZONTAL_PIXELS,
model, buffer, 0, VERTICAL_PIXELS));
The advantage of this approach is that you control the underlying pixel array. You could make changes to that array and call newPixels()
on your MemoryImageSource
, and it would update live. It also gives you complete power to define your own palette other than grayscale:
int[] cmap = new int[65536];
for(int i = 0; i < 65536; ++i) {
cmap[i] = (((i % 10000) * 256 / 10000) << 16)
| (((i % 20000) * 256 / 20000) << 8)
| (((i % 40000) * 256 / 40000) << 0);
}
ColorModel model = new IndexColorModel(16, 65536, cmap, 0, false, -1, DataBuffer.TYPE_USHORT);
This approach works fine if you just want to display the image on the screen:
JFrame frame = new JFrame();
frame.getContentPane().add(new JLabel(new ImageIcon(image)));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
However, if you wanted to write it out to a file and preserve the one-short-per-pixel format (say, to load into Matlab) then you're out of luck. The best you can do is to paint it into a BufferedImage
and save that with ImageIO
, which will save as RGB.
If you definitely need a BufferedImage
at the end, another approach is to apply the color palette yourself, calculate the RGB values, and then copy them into the image:
short[] data = /* your data */;
int[] cmap = /* as above */;
int[] rgb = new int[data.length];
for(int i = i; i < rgb.length; ++i) {
rgb[i] = cmap[data[i]];
}
BufferedImage image = new BufferedImage(
VERTICAL_PIXELS, HORIZONTAL_PIXELS,
BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, VERTICAL_PIXELS, HORIZONTAL_PIXELS,
pixels, 0, VERTICAL_PIXELS);