2017-04-14 70 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