是否有100%的Java替代ImageIO来读取JPEG文件?

我们正在使用Java2D来调整上传到我们网站的照片的大小,但是我们遇到了一个问题(一个看似旧的问题,参见: http : //forums.sun.com/thread.jspa?threadID = 5425569 ) – 一些特殊的JPEG当我们尝试ImageIO.read()包含其二进制数据的InputStream时,引发CMMException

 java.awt.color.CMMException: Invalid image format at sun.awt.color.CMM.checkStatus(CMM.java:131) at sun.awt.color.ICC_Transform.(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) ... 

(剪断了堆栈跟踪的剩余部分,这是我们的ImageIO.read()调用,servlet代码等)

我们将其缩小到特定相机拍摄的照片,然后我选择了一张触发此错误的照片: http : //img214.imageshack.us/img214/5121/estacaosp.jpg 。 我们注意到这只发生在Sun的JVM上(在Linux和Mac上,只是在1.6.0_20上测试过) – 一台带有OpenJDK的测试机器可以顺利读取相同的照片,这可能是由于JPEG阅读器的不同实现。

不幸的是,我们无法在生产中切换JVM,也无法使用ImageMagick( http://www.imagemagick.org/ )等本机相关解决方案。

考虑到这一点,我的问题是:是否存在替代可以处理链接照片之类的照片的ImageIO JPEG读取器? 如果没有,我们可以使用另一个100%纯Java照片大小调整解决方案吗?

谢谢!

一个可能有用的库可能是Java高级成像库( JAI )

使用这个库可能比使用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); } 

运行此代码后,图像似乎加载正常。 然后使用ParamaterBlock将其resize50%

最后,如果你想保存文件,你可以打电话:

 String filename2 = new String ("tofile.jpg"); String format = new String ("JPEG"); RenderedOp op = JAI.create ("filestore", image, filename2, format); 

我希望这能够帮到你。 祝你好运。

旧post,但供将来参考:

受此问题和链接的启发,我为ImageIO编写了一个JPEGImageReader插件,支持带有这些“坏”ICC颜色配置文件的JPEG图像(“问题”是ICC配置文件中的渲染意图与Java的ColorConvertOp不兼容) )。 它是普通的Java,不需要JAI。

源代码和链接的二进制版本可以从GitHub上的TwelveMonkeys项目免费获得。

我遇到了同样的问题。 我不愿意使用JAI,因为它已经过时,但看起来它是最短的解决方案。

此代码使用Sun的ImageIO(快速)或在发生此问题的少数情况下使用JAI将InputStream转换为BufferedImage:

 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(); } }