创建一个由 ByteBuffer 支持的 bufferedImage

Create a bufferedImage backed by a ByteBuffer

我想创建一个 BufferedImage,它使用预先分配的 ByteBuffer 作为其存储或由它“支持”。

我读到有人建议编写自定义 WritableRaster,但我没有看到涉及 ByteBuffers 的适当示例。 大多数这些网页现在也已失效。

我该怎么做?

看看我的MappedImageFactoryMappedFileBufferhere。它们是为使用内存映射文件缓冲区而创建的,但是由于它们使用相同的接口 (java.nio.Buffer),您应该能够轻松地修改它们以使用预分配的 ByteBuffers.

这些图像的渲染和显示速度可能不会非常快,但可能“足够好”。

有关更多想法,请参阅 this answer, using IntBuffers。这是为 ByteBuffer:

修改的代码
public class ByteBufferTest {
    public static void main(String[] args) {
        Dimension dim = new Dimension(100, 100);
        int size = dim.width * dim.height * 4;

        final ByteBuffer buf = ByteBuffer.allocate(size);

        DataBuffer dbuf = new DataBuffer(DataBuffer.TYPE_BYTE, size) {
            @Override
            public void setElem(int bank, int i, int val) {
                buf.put(i, (byte) val);
            }

            @Override
            public int getElem(int bank, int i) {
                return buf.get(i);
            }
        };

        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ColorModel cm = new ComponentColorModel(cs, new int[]{8, 8, 8, 8}, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

        SampleModel sm = cm.createCompatibleSampleModel(dim.width, dim.height);
        WritableRaster raster = new WritableRaster(sm, dbuf, new Point()) {};
        BufferedImage img = new BufferedImage(cm, raster, false, null);

        System.err.println("img: " + img);
    }
}

输出:

img: BufferedImage@4f3f5b24: type = 0 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@15aeb7ab transparency = 1 has alpha = true isAlphaPre = false ByteBufferTest@7b23ec81

如果你的 ByteBuffers 是使用 Java 数组(堆)分配的,你也可以使用完全标准的 BufferedImages,通过创建一个正常的 DataBubfferByte缓冲区的 array().

在试图解决同样的问题时偶然发现了这个问题。奇怪的是,以下代码似乎 运行 比公认的解决方案更快。不知道为什么 - 这看起来很无效...

final ByteBuffer pImageBuffer = ByteBuffer.allocateDirect((int) size);
final byte[] buffer = new byte[pImageBuffer.capacity()];
while (capturing) {
  // populate pImageBuffer via JNI
  pImageBuffer.rewind();
  for (int n = 0; n < pImageBuffer.capacity(); ++n) {
    buffer[n] = pImageBuffer.get(n);
  }
  pImageBuffer.clear();

  final BufferedImage retrievedImage = new BufferedImage(captureWidth, captureHeight, BufferedImage.TYPE_4BYTE_ABGR);
  retrievedImage.getRaster().setDataElements(0, 0, captureWidth, captureHeight, buffer);
}