使用 ImageIO.read() 生成的图像是不是仍使用传递给它的相同内存?

Posted

技术标签:

【中文标题】使用 ImageIO.read() 生成的图像是不是仍使用传递给它的相同内存?【英文标题】:Does the resulting image from using ImageIO.read() still use the same memory passed to it?使用 ImageIO.read() 生成的图像是否仍使用传递给它的相同内存? 【发布时间】:2020-07-02 07:01:54 【问题描述】:

我正在开发一个 OpenGL 项目,该项目需要我通过 JNI 库实现 JVM,以使用 JavaGraphics2D 渲染到 c++ 中的 OpenGL 映射缓冲区。我知道我可以使用指向映射缓冲区的void* 指针创建一个java.nio.ByteBuffer 对象:

jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity);

如果我通过将 ByteBuffer 转换为 byte[] 数组,将该数组包裹在 ByteArrayInputStream 周围并使用 ImageIO.read() 来传递它,那么最终 BufferedImage 仍将使用与void* 存储指针或 ImageIO 方法是否为 BufferedImage 存储分配新内存?即如果我使用 Java2DGraphics 绘制到 BufferedImage 上,是否会导致原始 void* 内存也被更改?

如果不是这样,我将不得不将 BufferedImage 数据复制到 ByteBuffer 中

【问题讨论】:

【参考方案1】:

ImageIO.read 处理各种输入源并分配自己的内存,它不与它返回的 BufferedImage 共享您的原始 byte[]。

所以你需要调用 ImageIO.write 来取回修改。

【讨论】:

是否有另一个我可以使用的类/库可以做到这一点? 我怀疑你会找到一些东西 - 如果存储扩展也会有问题。几乎所有的图像阅读器都会从某种形式的InputStream 中读取它们的源,并且不知道底层存储格式可能是 ByteBuffer、byte[]、文件/路径、ZIP/压缩、HTTP 连接。让ImageIO.write 保存到新的ByteArrayOutputStream 应该不难,然后将缓冲区复制回来。 @fsxflyer789Productions 您的原始内存已经与您从它创建的byte[] 数组分离。然后,您将数组包装在 ByteArrayInputStream 中,其读取操作原则上是将数据复制到目标存储中。除了生成的BufferedImage 的存储不可能连接到您的原始内存之外,当图像被修改时,您实际上期望什么?每次更新时要以原始图像格式重新编码的数据?图像解码根本不一定是可逆的过程。 @Holger 由于原始内存缓冲区连接到纹理,因此在 java 中对缓冲区所做的任何更改以反映原始内存本身的更改 @fsxflyer789Productions 当您使用ImageIO 时,这意味着源以特定的图像格式编码,png、jpeg、gif 等等。因此,您希望每当您更改BufferedImage 中的单个像素时,整个图像都会重新编码到源缓冲区?除了这个想法的疯狂开销之外,如果新编码的图片不适合原始缓冲区怎么办?压缩数据的大小取决于实际内容。

以上是关于使用 ImageIO.read() 生成的图像是不是仍使用传递给它的相同内存?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ImageIO.read 的问题

请问为啥arcgis纠正后的图像是黑色的呢?

ImageIO.read() 返回 403 错误

Java压缩图片ImageIO.read()报错

ImageIO.read() 返回 null

尝试使用 ImageIO.read(class.getResource(URL)) 加载图像,但 getResource 返回 null