You can't just cast an arbitrary databuffer to DataBufferByte
, you need to make sure it actually is the right type:
ByteBuffer byteBuffer;
DataBuffer dataBuffer = bi.getRaster().getDataBuffer();
if (dataBuffer instanceof DataBufferByte) {
byte[] pixelData = ((DataBufferByte) dataBuffer).getData();
byteBuffer = ByteBuffer.wrap(pixelData);
}
else if (dataBuffer instanceof DataBufferUShort) {
short[] pixelData = ((DataBufferUShort) dataBuffer).getData();
byteBuffer = ByteBuffer.allocate(pixelData.length * 2);
byteBuffer.asShortBuffer().put(ShortBuffer.wrap(pixelData));
}
else if (dataBuffer instanceof DataBufferShort) {
short[] pixelData = ((DataBufferShort) dataBuffer).getData();
byteBuffer = ByteBuffer.allocate(pixelData.length * 2);
byteBuffer.asShortBuffer().put(ShortBuffer.wrap(pixelData));
}
else if (dataBuffer instanceof DataBufferInt) {
int[] pixelData = ((DataBufferInt) dataBuffer).getData();
byteBuffer = ByteBuffer.allocate(pixelData.length * 4);
byteBuffer.asIntBuffer().put(IntBuffer.wrap(pixelData));
}
else {
throw new IllegalArgumentException("Not implemented for data buffer type: " + dataBuffer.getClass());
}
If your BufferedImage
is one of the standard types (BufferedImage.TYPE_*
other than TYPE_CUSTOM
) the above should work.
Note that special DatBuffer
subclasses may exist, and may store pixels in multiple banks, with different byte order, might be channel interleaved (rather than the standard pixel interleaved) etc. So the above code is still not completely general.
If you are to pass these ByteBuffer
s to native code, using allocateDirect(..)
and copying the pixels over might be faster, otherwise I think using wrap(..)
will make for both simpler code and be more efficient.