当使用 javax.imageio.ImageIO
从磁盘加载大分辨率 (9000x9000) JPEG 时,我的 Scala 应用程序需要 1 分钟多的时间。我尝试创建一个纯 Java 项目,但它仍然需要很长时间 - 大约 30 秒。
这是我加载图片的方式:
File file = new File("/Users/the21st/slow2.jpg");
BufferedImage image = ImageIO.read(file);
有什么方法可以提高在 Java 中读取渐进式编码的大分辨率 JPEG 的性能?
有问题的图片是this one (版主,请不要再重新上传到其他托管站点,以免编码/质量发生变化)
最佳答案
好的,这是我目前的发现(老实说,它们有点令人担忧......)。
使用与 Oracle JRE 捆绑在一起的用于 ImageIO 的标准 JPEG 插件:
BufferedImage image = ImageIO.read(file);
在我的计算机(MacBookPro/2.8GHz i7)上大约 18 秒 读取图像。
使用我的 JPEG plugin for ImageIO ,它使用了稍微不同的代码路径(即,您可能会通过获取 ImageReader
并调用 readRaster()
方法获得相同的结果,然后创建一个 BufferedImage
来自于此。代码非常重要,因此如果您想查看代码,请引用项目页面):
BufferedImage image = ImageIO.read(file);
在我的计算机上大约 8 秒 读取图像。
使用我的 BufferedImageFactory
类和 AWT 工具包
:
BufferedImage image = new BufferedImageFactory(Toolkit.getDefaultToolkit().createImage(file.getAbsolutePath())).getBufferedImage();
在我的计算机上~2.5 秒 读取图像。
使用 sun.awt.codec
中已弃用的 JPEGImageDecoder
类:
BufferedImage image = new JPEGImageDecoderImpl(new FileInputStream(file)).decodeAsBufferedImage();
在我的电脑上读取图像 ~1.7 秒。
因此,这意味着我们应该能够在不到 2 秒的时间内读取此图像,即使是在 Java 中也是如此。 JPEGImageReader
的性能在这种情况下简直荒谬,我真的很想知道为什么。前面已经提到了,它似乎必须与渐进解码一起使用,但仍然应该比这更好。
更新:
为了好玩,我创建了一个由 LibJPEG-Turbo Java API 支持的快速 PoC ImageReader
插件.它还不是很复杂,但它允许像这样的代码:
BufferedImage image = ImageIO.read(file);
在我的电脑上<1.5 秒阅读图像。
附言:I used to maintain ImageIO wrappers for JMagick (类似于@Jordan Doyle 提到的代码,但它允许您针对 ImageIO API 进行编程),但是我停止了,因为它的工作量太大了。也许我必须重新考虑...如果您不介意依赖 JNI/ native 代码安装,至少也值得检查一下他的解决方案。
关于java - 用 Java 读取渐进式编码的 9000x9000 JPEG 需要 1 分钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29705050/