我有一个应用程序需要展示一张非常大的图片(从磁盘上的png文件),而屏幕上只会显示图片的一小部分。然而,这个可见部分可以在大图中快速移动。
将整个图像一次性加载到BufferedImage中不是一个好主意,因为它可能有1万到10万像素宽,但是其在磁盘上的大小并不是很大(可能只有几MB),所以问题在于只加载需要显示的部分。
我尝试创建了一个如下所示的ImageReader:
然后有一种获取子图像的方法,就是像这样:
将整个图像一次性加载到BufferedImage中不是一个好主意,因为它可能有1万到10万像素宽,但是其在磁盘上的大小并不是很大(可能只有几MB),所以问题在于只加载需要显示的部分。
我尝试创建了一个如下所示的ImageReader:
FileImageInputStream is = new FileImageInputStream(imageFile);
ImageReader imageReader = ImageIO.getImageReaders(is).next();
ImageReader.setInput(is, false, true);
ImageReadParam readParameters = imageReader.getDefaultReadParam();
然后有一种获取子图像的方法,就是像这样:
private BufferedImage loadFrame(int x, int y, int w, int h) {
readParameters.setSourceRegion(new Rectangle(x,y,w,h));
try {
return imageReader.read(0, readParameters);
} catch (IOException ex) {
return null;
}
}
这个方法原则上可行,但速度太慢。所以在图像快速移动时,它会有很大的延迟。
我还尝试过事先拆分源图像,以便我有一堆小图像放在磁盘上,然后根据需要使用ImageIO.read(getImageFile(x,y))
加载,其中getImageFile(x,y)
将返回该位置的适当文件
。这种方法实际上要快得多,而且完全可用。
所以我想我找到了解决办法,但这种方式似乎有些笨拙。除了需要对源图像进行一些准备外,它还需要大量的磁盘访问(虽然我想这可能已经被缓存了)。
所以我的问题是:最好的方法是什么?(为什么从磁盘加载图像比从ImageReader加载图像的一部分更快?)