问题描述
我对使用BufferedImage对象的唯一担心是,对于一个很大的图像(例如60000x32000),它将导致JVM在有限的JVM堆空间上使用OOM关闭。但是,ImageIO.read方法的
JavaDocs讲述了一些有关控件缓存的内容。
在这种情况下,控件缓存是什么?
这是否意味着ImageIO.read将磁盘上的图像缓存用于大图像?
请参阅JavaDocs和下面的ImageIO.read方法:
/ **
*返回< code> BufferedImage< / code>作为解码
*的结果,所提供的< code>文件< / code>带有< code> ImageReader< / code>
*从当前注册的那些中自动选择。
*< code>文件< / code>包裹在
*< code> ImageInputStream< / code>中。如果没有注册
*< code> ImageReader< / code>声称能够读取
*结果流,< code> null< / code>返回。
*
*< p>来自< code> getUseCache< / code>和
*< code> getCacheDirectory< / code>的当前缓存设置。将用于控制
*< code> ImageInputStream< / code>创建的。
*
*< p>请注意,没有< code> read< / code>以
*文件名作为< code> String< / code>的方法;在
*创建一个< code> File< / code>之后使用此方法代替从文件名。
*
*< p>该方法不尝试定位可以直接从
*< code> File< / code>中读取的
*< code> ImageReader< / code>。可以使用
*< code> IIORegistry< / code>和< code> ImageReaderSpi< / code>。
*
* @param输入一个< code>文件< / code>阅读。
*
* @返回一个< code> BufferedImage< / code>包含输入的已解码
*内容,或< code> null< / code>。
*
* @exception IllegalArgumentException如果< code> input< / code>是
*< code> null< / code>。
* @exception IOException如果读取期间发生错误。
* /
公共静态BufferedImage读取(文件输入)引发IOException {
if(input == null){
throw new IllegalArgumentException( input == null!);
}
if(!input.canRead()){
抛出new IIOException(无法读取输入文件!);
}
ImageInputStream stream = createImageInputStream(input);
if(stream == null){
抛出new IIOException(无法创建ImageInputStream!);
}
BufferedImage bi = read(stream);
if(bi == null){
stream.close();
}
return bi;
}
在这种情况下,表示 read
方法将使用 getUseCache
和 getCacheDirectory
控制是否允许缓存( getUseCache
),如果允许,则在哪里可以存储临时文件( getCacheDirectory
)
ImageIO中的缓存没有什么特别的,可能仅用于处理不可搜索的流。例如,当ImageIO需要确定图像的大小时,可能需要读取流的重要部分。然后,可能需要重新读取流的该部分以进行实际的解码。
对于支持搜索的文件和流,这不是问题。只需在开始解码时重新阅读前面的部分。举例来说,HTTP流没有这种选择,在某些情况下,可能需要将流的一部分存储在某处以便稍后对其进行解码。可以在内存( MemoryCacheImageInputStream
)或临时文件( FileCacheImageInputStream
)中。
使用哪种类型的流留给 ImageIO
类,该类根据缓存设置和基础媒体来动态决定。
因此,在处理非常大的图像时,我认为这不会帮助您。您仍然需要确保VM有足够的空间对其进行解码。
My only fear of using BufferedImage object is that for a very large image of say 60000x32000 it will result in JVM shutting down with OOM on a limited JVM heap space. However,JavaDocs of ImageIO.read method says something about "control caching".
What is control caching in this context?
Does that mean ImageIO.read uses caching of image on disk for large image?
Refer to JavaDocs and ImageIO.read method below:
/**
* 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;
}
In this context, it just means the read
method will use the settings from getUseCache
and getCacheDirectory
to control if caching will be allowed (getUseCache
) and if so, where it can store temporary files (getCacheDirectory
).
The caching in ImageIO is nothing spectacular and probably only there for dealing with non-seekable streams. For example, when ImageIO needs to determine the size of the image, it may need to read a significant portion of the stream. It then may need to re-read that part of the stream again to do the actual decoding.
For files and streams that support seeking, this is no issue as you can just re-read an earlier part when starting the decode. For say a HTTP stream, there is no such option and in those cases part of the stream may need to be stored somewhere in order to decode it later. This can be in memory (MemoryCacheImageInputStream
) or in a temporary file (FileCacheImageInputStream
).
Which type of stream is used is left up to the ImageIO
class which dynamically decides this based on the cache settings and the underlying media.
So, I donot think this will help you when dealing with very large images. You will still need to make sure the VM has sufficient space for decoding them.
这篇关于在ImageIO中控制缓存的含义是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!