用 Java 读取渐进编码的 9000x9000 JPEG 需要 1 分钟 [英] Reading a progressively encoded 9000x9000 JPEG in Java takes 1 minute
问题描述
当使用 javax.imageio.ImageIO
从磁盘加载大分辨率 (9000x9000) JPEG 时,在我的 Scala 应用程序中需要 1 多分钟.我尝试创建一个仅限 Java 的项目,但仍然需要很长时间 - 大约 30 秒.
When using javax.imageio.ImageIO
to load a large-resolution (9000x9000) JPEG from disk, it takes more than 1 minute in my scala application. I tried creating a Java-only project, but it still takes too long - around 30 seconds.
这是我加载图像的方式:
This is how I load the image:
File file = new File("/Users/the21st/slow2.jpg");
BufferedImage image = ImageIO.read(file);
有什么方法可以提高在 Java 中读取渐进编码的大分辨率 JPEG 的性能吗?
Is there any way to improve performance on reading progressively encoded large-res JPEGs in Java?
有问题的图片是这个(版主,请不要t 重新上传到其他托管站点,以便编码/质量不会改变)
The image in question is this one (moderators, please don't reupload to other hosting site again so that encoding / quality doesn't change)
推荐答案
好的,这是我目前的发现(说实话,它们有点令人担忧......).
Ok, here's my findings so far (and to be honest, they are a little worrying...).
使用与 Oracle JRE 捆绑的 ImageIO 的标准 JPEG 插件:
Using the standard JPEG plugin for ImageIO bundled with the Oracle JRE:
BufferedImage image = ImageIO.read(file);
在我的计算机(MacBookPro/2.8GHz i7)上大约 18 秒读取图像.
Reads the image in roughly 18 seconds on my computer (a MacBookPro/2.8GHz i7).
使用我的 ImageIO 的 JPEG 插件,它使用稍微不同的代码路径(即,您通过获取 ImageReader
并调用 readRaster()
方法,然后从中创建一个 BufferedImage
可能会得到相同的结果.代码是非-微不足道,所以如果你想看代码,请参考项目页面):
Using my JPEG plugin for ImageIO, which uses a slightly different code path (i.e., you can probably get the same results by obtaining the ImageReader
and invoking the readRaster()
method, then creating a BufferedImage
from that. The code is non-trivial, so please refer tho the project page if you like to see the code):
BufferedImage image = ImageIO.read(file);
在我的计算机上大约 8 秒读取图像.
Reads the image in roughly 8 seconds on my computer.
使用我的 BufferedImageFactory
类和 AWT Toolkit
:
BufferedImage image = new BufferedImageFactory(Toolkit.getDefaultToolkit().createImage(file.getAbsolutePath())).getBufferedImage();
在我的计算机上~2.5 秒读取图像.
Reads the image in ~2.5 seconds on my computer.
使用 sun.awt.codec
中已弃用的 JPEGImageDecoder
类:
Using the deprecated JPEGImageDecoder
class from sun.awt.codec
:
BufferedImage image = new JPEGImageDecoderImpl(new FileInputStream(file)).decodeAsBufferedImage();
在我的计算机上~1.7 秒读取图像.
Reads the image in ~1.7 seconds on my computer.
所以,这意味着我们应该能够在不到 2 秒的时间内读取此图像,即使是在 Java 中也是如此.在这种情况下,JPEGImageReader
的性能非常荒谬,我真的很想知道为什么.前面已经提到,它似乎必须与渐进式解码有关,但仍然应该比这更好.
So, this means that we should be able to read this image in less than 2 seconds, even in Java. The performance from the JPEGImageReader
is just ridiculous in this case, and I really like to know why. As already mentioned, it seems to have to with the progressive decoding, but still, it should be better than this.
更新:
只是为了好玩,我创建了一个由 ImageReader 插件"nofollow">LibJPEG-Turbo Java API.它还不是很复杂,但它允许代码如下:
Just for the fun of it, I created a quick PoC ImageReader
plugin backed by the LibJPEG-Turbo Java API. It's not very sophisticated yet, but it allows for code like:
BufferedImage image = ImageIO.read(file);
读取中的图像<1.5 秒在我的电脑上.
PS:我曾经为 JMagick 维护 ImageIO 包装器(类似于@Jordan Doyle 提到的代码,但它允许您针对 ImageIO API 进行编程),但是我停止了,因为它工作量太大.也许我必须重新考虑...至少也值得查看他的解决方案,如果您不介意依赖 JNI/本机代码安装.
PS: I used to maintain ImageIO wrappers for JMagick (similar to the code mentioned by @Jordan Doyle, but it would allow you to program against the ImageIO API), however I stopped as it was too much work. Maybe I have to reconsider... At least it's worth checking out his solution as well, if you don't mind on relying on JNI/native code installation.
这篇关于用 Java 读取渐进编码的 9000x9000 JPEG 需要 1 分钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!