将缓冲图像转换为不带 I/O 的字节 []

嗨,我在内存中有一个BufferedImage实例,并希望将其转换为byte[]以编码为base64字符串,而无需I / O操作以考虑性能。我使用以下 API:

ByteArrayOutputStream baos = new ByteArrayOutputStream ();
ImageIO.write(image,"png",baos);
return baos.toByteArray();

但是,此 API 仍会将映像隐式写入 OS 临时目录,如果基础操作系统临时目录已满且无法创建临时文件,这将导致失败。堆栈跟踪:

Caused by: java.io.IOException: No space left on device
    at java.io.RandomAccessFile.write(RandomAccessFile.java:493)
    at javax.imageio.stream.FileCacheImageOutputStream.write(FileCacheImageOutputStream.java:134)
    at javax.imageio.stream.ImageOutputStreamImpl.write(ImageOutputStreamImpl.java:66)
    at com.sun.imageio.plugins.png.PNGImageWriter.write_magic(PNGImageWriter.java:376)
    at com.sun.imageio.plugins.png.PNGImageWriter.write(PNGImageWriter.java:1115)
    at javax.imageio.ImageWriter.write(ImageWriter.java:628)
    at javax.imageio.ImageIO.write(ImageIO.java:1480)
    at javax.imageio.ImageIO.write(ImageIO.java:1554)

有没有一种有效的(如内存中转换或高效 I/O)方法可以在没有 I/O 的情况下进行转换?请指教。


答案 1

通过 ImageIO.setUseCache() 方法禁用 ImageIO 缓存:

ImageIO.setUseCache(false);

根据javadoc,它默认处于打开状态:

设置一个标志,指示在创建 ImageInputStreams 和 ImageOutputStreams 时是否应使用基于磁盘的缓存文件。

从标准 InputStream>读取时,可能需要将以前读取的信息保存在缓存中,因为基础流不允许重新读取数据。同样,在写入标准 OutputStream 时,可以使用缓存来允许在将以前写入的值刷新到最终目标之前对其进行更改。

缓存可以驻留在主内存中或磁盘上。将此标志设置为 false 将不允许将来的流中使用磁盘,这在处理小映像时可能是有利的,因为创建和销毁文件的开销已被删除。

启动时,该值设置为 true。


答案 2

两次提及都是正确的。但是,如果您不想全局禁用 ImageIO 的磁盘缓存,另一种方法是将流显式包装在 (执行内存中缓存而不是磁盘缓存):ImageIO.setUseCache(false)MemoryCacheImageOutputStream

ByteArrayOutputStream baos = new ByteArrayOutputStream ();
ImageOutputStream stream = new MemoryCacheImageOutputStream(baos);
ImageIO.write(image, "png", stream);
stream.close();
return baos.toByteArray();

推荐