用 Java 读取渐进编码的 9000x9000 JPEG 需要 1 分钟 [英] Reading a progressively encoded 9000x9000 JPEG in Java takes 1 minute

查看:38
本文介绍了用 Java 读取渐进编码的 9000x9000 JPEG 需要 1 分钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用 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.getAbsolutePat‌​h())).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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆