2017-04-14 69 views
0

我唯一担心使用BufferedImage对象的原因是,对于非常大的图像60000x32000,它将导致JVM在有限的JVM堆空间上使用OOM关闭。然而,ImageIO.read方法的JavaDocs说了一些关于“控制缓存”的内容。ImageIO中控制缓存意味着什么

什么是控制缓存在这种情况下?

这是否意味着ImageIO.read使用磁盘上的图像缓存大图像?

参考的JavaDoc和下面ImageIO.read方法:

 /** 
     * Returns a <code>BufferedImage</code> as the result of decoding 
     * a supplied <code>File</code> with an <code>ImageReader</code> 
     * chosen automatically from among those currently registered. 
     * The <code>File</code> is wrapped in an 
     * <code>ImageInputStream</code>. If no registered 
     * <code>ImageReader</code> claims to be able to read the 
     * resulting stream, <code>null</code> is returned. 
     * 
     * <p> The current cache settings from <code>getUseCache</code>and 
     * <code>getCacheDirectory</code> will be used to control caching in the 
     * <code>ImageInputStream</code> that is created. 
     * 
     * <p> Note that there is no <code>read</code> method that takes a 
     * filename as a <code>String</code>; use this method instead after 
     * creating a <code>File</code> from the filename. 
     * 
     * <p> This method does not attempt to locate 
     * <code>ImageReader</code>s that can read directly from a 
     * <code>File</code>; that may be accomplished using 
     * <code>IIORegistry</code> and <code>ImageReaderSpi</code>. 
     * 
     * @param input a <code>File</code> to read from. 
     * 
     * @return a <code>BufferedImage</code> containing the decoded 
     * contents of the input, or <code>null</code>. 
     * 
     * @exception IllegalArgumentException if <code>input</code> is 
     * <code>null</code>. 
     * @exception IOException if an error occurs during reading. 
     */ 
     public static BufferedImage read(File input) throws IOException { 
      if (input == null) { 
       throw new IllegalArgumentException("input == null!"); 
      } 
      if (!input.canRead()) { 
       throw new IIOException("Can't read input file!"); 
      } 

      ImageInputStream stream = createImageInputStream(input); 
      if (stream == null) { 
       throw new IIOException("Can't create an ImageInputStream!"); 
      } 
      BufferedImage bi = read(stream); 
      if (bi == null) { 
       stream.close(); 
      } 
      return bi; 
     } 
+0

我认为@ john16384可以非常准确地回答你的问题。但是,如果您喜欢使用磁盘缓存映像来避免OOME,则可以尝试我的['MappedImageFactory'](https://github.com/haraldk/TwelveMonkeys/blob/master/sandbox/sandbox-common/src/main/的java/COM/twelvemonkeys /图像/ MappedImageFactory.java)。通过使用'ImageReadParam.setDestination(mappedImage)',你可以将'ImageIO'直接读入这些图像。 – haraldK

+0

这也适用于CMYK色彩空间系列吗? – t6nand

+0

我相信是的。但我没有尝试过,并且像往常一样代码没有保修。什么让你相信它不会工作? – haraldK

回答

2

在这种情况下,它只是意味着read方法将使用从getUseCachegetCacheDirectory的设置来控制,如果高速缓存将被允许(getUseCache)和如果是这样,它可以存储临时文件的位置(getCacheDirectory)。

ImageIO中的缓存没有什么特别之处,可能只有那些用于处理不可查找的流。例如,当ImageIO需要确定图像的大小时,可能需要读取流的重要部分。然后可能需要重新读取该部分流以进行实际解码。

对于支持查找的文件和流,这不是问题,因为您可以在开始解码时重新读取前面的部分。对于说一个HTTP流,没有这样的选择,在这些情况下,部分流可能需要存储在某处以便稍后解码。这可以在内存(MemoryCacheImageInputStream)或临时文件(FileCacheImageInputStream)中。

使用哪种类型的流是由ImageIO类决定的,该类根据缓存设置和基础介质动态决定。

所以,我不认为这会帮助你处理非常大的图像。您仍然需要确保虚拟机有足够的空间来解码它们。

+0

感谢您提供有用的见解。 – t6nand