我有一个应用程序需要显示一个非常大的图像(来自磁盘上的png),只有一小部分图像在屏幕上随时可见.但是,可见部分可以在大图像周围快速移动.
将整个图像一次加载到BufferedImage中并不是一个好主意,因为它可以是10 000 – 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)将返回相应的文件for那个位置.这种方法实际上更快,更完全可用.
所以我想我有办法让这个工作,但这样做似乎有点尴尬.除了需要对源映像进行一些准备之外,它还需要大量的磁盘访问(尽管我猜这可能是在某处缓冲的).
所以我的问题是:最好的方法是什么? (为什么从磁盘加载图像比从ImageReader加载图像的一部分更快?)
解决方法:
PNG是一种压缩格式,你不能只是打开文件并寻找一个特定的位置来开始读取区域(就像你可以用位图〜当然读完文件头后).在开始提取区域之前,需要加载(解析/解压缩)整个PNG. (http://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header)
如果你想牺牲磁盘空间来改善内存(RAM)的使用和性能……
>您可以将图像分割并仅加载为用户构建视图所需的网格块.
>
> 1×1.png,1×2.png,2×1.png,2×2.png – 如果用户正在查看左上角,则只需加载1×1.png等.
>您可以将图像转换为位图BMP图像在磁盘上会大得多,但您将能够提取它的特定区域而无需处理整个文件.
标签:java,image 来源: https://codeday.me/bug/20190703/1367080.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。