使用 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(class.getResource(URL)) 加载图像,但 getResource 返回 null