【发布时间】:2020-07-06 19:23:01
【问题描述】:
我想创建一个BufferedImage,它使用预先分配的ByteBuffer 作为其存储或由它“支持”。
我读到有人建议编写自定义 WritableRaster,但我没有看到涉及 ByteBuffers 的适当示例。
这些网页中的大多数现在也已失效。
我该怎么做呢?
【问题讨论】:
标签: java raster bufferedimage bytebuffer
我想创建一个BufferedImage,它使用预先分配的ByteBuffer 作为其存储或由它“支持”。
我读到有人建议编写自定义 WritableRaster,但我没有看到涉及 ByteBuffers 的适当示例。
这些网页中的大多数现在也已失效。
我该怎么做呢?
【问题讨论】:
标签: java raster bufferedimage bytebuffer
看看我的MappedImageFactory 和MappedFileBuffer 课程here。它们是为使用内存映射文件缓冲区而设计的,但由于它们使用相同的接口 (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$2@7b23ec81
如果您的ByteBuffers 是使用Java 数组(堆)分配的,您也可以使用完全标准的BufferedImages,通过在缓冲区的array() 周围创建一个普通的DataBubfferByte。
【讨论】:
偶然发现这个问题试图解决同样的问题。奇怪的是,以下代码似乎比公认的解决方案运行得更快。不知道为什么 - 这看起来很无效......
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);
}
【讨论】: