Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting BufferedImage to ByteBuffer

I'm trying to convert a Buffered image into a ByteBuffer but i get this exception

java.awt.image.DataBufferInt cannot be cast to java.awt.image.DataBufferByte

can someone please help me out and suggest a good method of conversion.

Source:

public static ByteBuffer convertImageData(BufferedImage bi) 
{
    byte[] pixelData = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
    //        return ByteBuffer.wrap(pixelData);
    ByteBuffer buf = ByteBuffer.allocateDirect(pixelData.length);
    buf.order(ByteOrder.nativeOrder());
    buf.put(pixelData);
    buf.flip();
    return buf;
}

this is my object

 ByteBuffer buf = convertImageData(image);
like image 787
Sumal Perera Avatar asked Mar 27 '15 13:03

Sumal Perera


People also ask

What does BufferedImage mean?

A BufferedImage is comprised of a ColorModel and a Raster of image data. The number and types of bands in the SampleModel of the Raster must match the number and types required by the ColorModel to represent its color and alpha components. All BufferedImage objects have an upper left corner coordinate of (0, 0).

What is the difference between BufferedImage and image?

A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage. A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image's pixel data.

How do I change an image to BufferedImage?

BufferedImage buffer = ImageIO. read(new File(file)); to Image i.e in the format something like : Image image = ImageIO.


1 Answers

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 ByteBuffers 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.

like image 115
Harald K Avatar answered Sep 22 '22 02:09

Harald K