将 BufferedImage 转换为 ByteBuffer

Sum*_*era 6 java bufferedimage bytebuffer image-processing

我正在尝试将缓冲图像转换为 ByteBuffer,但出现此异常

java.awt.image.DataBufferInt cannot be cast to java.awt.image.DataBufferByte
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我并建议一个好的转换方法。

来源:

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;
}
Run Code Online (Sandbox Code Playgroud)

这是我的对象

 ByteBuffer buf = convertImageData(image);
Run Code Online (Sandbox Code Playgroud)

har*_*ldK 5

您不能将任意数据缓冲区强制转换为DataBufferByte,您需要确保它实际上是正确的类型:

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());
}
Run Code Online (Sandbox Code Playgroud)

如果您BufferedImage是标准类型之一(BufferedImage.TYPE_*除了TYPE_CUSTOM),则上述内容应该有效。

请注意,DatBuffer可能存在特殊的子类,并且可能将像素存储在多个组中,具有不同的字节顺序,可能是通道交错(而不是标准像素交错)等。因此上述代码仍然不完全通用。

如果您要将这些ByteBuffers传递给本机代码,使用allocateDirect(..)和复制像素可能会更快,否则我认为使用wrap(..)将使代码更简单,效率更高。


eeq*_*eeq 3

如果你想对图像数据进行编码,你可能需要在这里使用ImageIO。像这样的东西:

public static ByteBuffer convertImageData(BufferedImage bi) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        ImageIO.write(bi, "png", out);
        return ByteBuffer.wrap(out.toByteArray());
    } catch (IOException ex) {
        //TODO
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

这是支持的格式的列表

  • 虽然你的代码可以编译并运行,但它确实做了一些与OP在他的代码块中试图实现的完全不同的事情。代码似乎期望一个包含“原始”像素的字节缓冲区,他在这里得到的是一个包含 PNG 文件的缓冲区。 (4认同)