是否有 100% Java 替代 ImageIO 来读取 JPEG 文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2999528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a 100% Java alternative to ImageIO for reading JPEG files?
提问by chesterbr
We are using Java2D to resize photos uploaded to our website, but we run into an issue (a seemingly old one, cf.: http://forums.sun.com/thread.jspa?threadID=5425569) - a few particular JPEGs raise a CMMExceptionwhen we try to ImageIO.read()an InputStream containing their binary data:
我们正在使用 Java2D 来调整上传到我们网站的照片的大小,但我们遇到了一个问题(一个看似老的问题,参见:http: //forums.sun.com/thread.jspa?threadID=5425569)——一些特定的 JPEGCMMException当我们尝试ImageIO.read()包含其二进制数据的 InputStream时引发 a :
java.awt.color.CMMException: Invalid image format
at sun.awt.color.CMM.checkStatus(CMM.java:131)
at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:516)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1114)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1082)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897)
at javax.imageio.ImageIO.read(ImageIO.java:1422)
at javax.imageio.ImageIO.read(ImageIO.java:1326)
...
(snipped the remainder of the stack trace, which is our ImageIO.read()call, servlet code and such)
(剪掉堆栈跟踪的其余部分,即我们的ImageIO.read()调用、servlet 代码等)
We narrowed it down to photos taken on specific cameras, and I selected a photo that triggers this error: http://img214.imageshack.us/img214/5121/estacaosp.jpg. We noticed that this only happens with Sun's JVM (on Linux and Mac, just tested it on 1.6.0_20) - a test machine with OpenJDK reads the same photos without a hitch, possibly due to a different implementation of the JPEG reader.
我们将范围缩小到在特定相机上拍摄的照片,我选择了一张触发此错误的照片:http: //img214.imageshack.us/img214/5121/estacaosp.jpg。我们注意到这只发生在 Sun 的 JVM 上(在 Linux 和 Mac 上,刚刚在 1.6.0_20 上测试过)——一台带有 OpenJDK 的测试机器可以顺利读取相同的照片,这可能是由于 JPEG 阅读器的不同实现。
Unfortunately, we are unable to switch JVMs in production, nor to use native-dependent solutions such as ImageMagick ( http://www.imagemagick.org/).
不幸的是,我们无法在生产中切换 JVM,也无法使用依赖本机的解决方案,例如 ImageMagick ( http://www.imagemagick.org/)。
Considering that, my question is: Does a replacement for ImageIOs JPEG reader which can handle photos such as the linked one exist? If not, is there another 100% pure Java photo resizing solution which we can use?
考虑到这一点,我的问题是:是否有替代 ImageIOs JPEG 阅读器的替代品,它可以处理链接的照片等照片?如果没有,我们可以使用另一种 100% 纯 Java 照片大小调整解决方案吗?
Thank you!
谢谢!
采纳答案by gruntled
One possibly useful library for you could be the Java Advanced Imaging Library (JAI)
一个可能对您有用的库可能是 Java Advanced Imaging Library ( JAI)
Using this library can be quite a bit more complicated than using ImageIO but in a quick test I just ran, it did open and display the problem image file you linked.
使用这个库可能比使用 ImageIO 复杂得多,但在我刚刚运行的快速测试中,它确实打开并显示了您链接的问题图像文件。
public static void main(String[] args) {
RenderedImage image = JAI.create("fileload", "estacaosp.jpg");
float scale=(float) 0.5;
ParameterBlock pb = new ParameterBlock();
pb.addSource(image);
pb.add(scale);
pb.add(scale);
pb.add(1.0F);
pb.add(1.0F);
pb.add(new InterpolationNearest() );// ;InterpolationBilinear());
image = JAI.create("scale", pb);
// Create an instance of DisplayJAI.
DisplayJAI srcdj = new DisplayJAI(image);
JScrollPane srcScrollPaneImage = new JScrollPane(srcdj);
// Use a label to display the image
JFrame frame = new JFrame();
frame.getContentPane().add(srcScrollPaneImage, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
After running this code the image seems to load fine. It is then resized by 50% using the ParamaterBlock
运行此代码后,图像似乎加载良好。然后使用 ParamaterBlock 将其大小调整为 50%
And finally if you wish to save the file you can just call :
最后,如果你想保存文件,你可以调用:
String filename2 = new String ("tofile.jpg");
String format = new String ("JPEG");
RenderedOp op = JAI.create ("filestore", image, filename2, format);
I hope this helps you out. Best of luck.
我希望这能够帮到你。祝你好运。
回答by haraldK
Old post, but for future reference:
旧帖子,但供将来参考:
Inspired by this question and links found here, I've written a JPEGImageReader plugin for ImageIO that supports JPEG images with these kind of "bad" ICC color profiles (the "issue" is the rendering intent in the ICC profile is incompatible with Java's ColorConvertOp). It's plain Java and does not require JAI.
受此问题和此处找到的链接的启发,我为 ImageIO 编写了一个 JPEGImageReader 插件,该插件支持具有此类“坏”ICC 颜色配置文件的 JPEG 图像(“问题”是 ICC 配置文件中的渲染意图与 Java 的 ColorConvertOp 不兼容)。它是普通的 Java,不需要 JAI。
The source code and linked binary builds are freely available from the TwelveMonkeys projecton GitHub.
源代码和链接的二进制构建可从GitHub 上的TwelveMonkeys 项目免费获得。
回答by Florent
I faced the same issue. I was reluctant to use JAI as it is outdated but it looks like it's the shortest solution.
我遇到了同样的问题。我不愿意使用 JAI,因为它已经过时了,但看起来它是最短的解决方案。
This code converts an InputStream to a BufferedImage, using sun's ImageIO (fast) or in the few cases where this problem occur, using JAI:
此代码将 InputStream 转换为 BufferedImage,使用 sun 的 ImageIO(快速)或在出现此问题的少数情况下,使用 JAI:
public static BufferedImage read(InputStream is) throws IOException {
try {
// We try it with ImageIO
return ImageIO.read(ImageIO.createImageInputStream(is));
} catch (CMMException ex) {
// If we failed...
// We reset the inputStream (start from the beginning)
is.reset();
// And use JAI
return JAI.create("stream", SeekableStream.wrapInputStream(is, true)).getAsBufferedImage();
}
}

