在没有I / O的情况下将BufferedImage转换为byte []

时间:2012-04-19 19:51:05

标签: java bufferedimage javax.imageio in-memory

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

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

但是,此API仍隐式将映像写入OS临时目录,如果底层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)?请指教。

4 个答案:

答案 0 :(得分:11)

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

ImageIO.setUseCache(false);

默认情况下根据javadoc开启:

  

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

     

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

     

缓存可能驻留在主内存或磁盘上。将此标志设置为false将禁止将磁盘用于将来的流,这在处理小图像时可能是有利的,因为删除了创建和销毁文件的开销。

     

启动时,该值设置为true。

答案 1 :(得分:4)

ImageIO.setUseCache(false)的两个提及都是正确的。但是,如果您不想全局禁用ImageIO的磁盘缓存,则可以选择将流显式包装在MemoryCacheImageOutputStream中(它使用内存缓存而不是磁盘缓存):

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

答案 2 :(得分:3)

默认情况下,即使您只使用流,ImageIO也会将其缓存写入磁盘。尝试使用以下命令禁用缓存:

ImageIO.setUseCache(false);

答案 3 :(得分:1)

如果您的图像是字节格式,

((DataBufferByte)img.getRaster().getDataBuffer()).getData()会自动返回一个字节数组。根本不需要任何IO。