奇怪的PNG错误:IHDR块的长度不正确

时间:2014-01-26 04:03:39

标签: java png bufferedimage javax.imageio

继承错误:

Exception in thread "main" javax.imageio.IIOException: I/O error reading PNG header!
    at com.sun.imageio.plugins.png.PNGImageReader.readHeader(PNGImageReader.java:307)
    at com.sun.imageio.plugins.png.PNGImageReader.readMetadata(PNGImageReader.java:637)
    at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1212)
    at com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1560)
    at javax.imageio.ImageIO.read(ImageIO.java:1422)
    at javax.imageio.ImageIO.read(ImageIO.java:1282)
    at Bundle.iconExists(Bundle.java:139)
    at Bundle.dPhIconExists(Bundle.java:158)
    at BundleAnalyzer.supports6(BundleAnalyzer.java:14)
    at TheifReader.<init>(TheifReader.java:14)
    at TheifReader.main(TheifReader.java:63)
Caused by: javax.imageio.IIOException: Bad length for IHDR chunk!
    at com.sun.imageio.plugins.png.PNGImageReader.readHeader(PNGImageReader.java:239)
    ... 10 more

并且代表了导致它的代码:

        bimg = ImageIO.read(icons[i]);

图标是一个文件数组。奇怪的是,我的电脑可以在任何图像浏览器中读取图像。谷歌搜索错误给了我没有结果。我需要阅读大量图像,除了将图像转换为BufferedImage之外,还有另一种获取图像尺寸的方法吗?这会解决问题吗?有没有办法修复这些图像?我通过从iOS设备收集应用程序图标来获取它们。来自我自己的设备的测试没有产生任何错误,尽管之前作为zip文件的一部分发送的测试虽然以相同的方式收集,但是会定期产生此错误。我所知道的关于压缩的一切都告诉我这不应该发生。我不知道从哪里开始寻找,真的需要修复。 Here is an example of a failed image

我应该注意,对于我的程序的这一部分,我需要的只是图像尺寸。我相信这可以通过阅读元数据来获得,但我也无法通过java找到具体内容。

1 个答案:

答案 0 :(得分:5)

根据PNG specifiaction

  

<强> 4.1.1。 IHDR图像标题

     

IHDR块必须首先出现。

您的示例图像包含自定义关键块CgBI作为第一个块,并且不符合此规范。这就是你得到例外的原因。

实际上,您的图片似乎是“iOS优化的PNG”。

来自http://fileformats.archiveteam.org/wiki/CgBI

  

与PNG不兼容。由于未知的“关键块”,不支持它的标准PNG解码器将会正常失败。

现在,com.sun.imageio.plugins.png.PNGImageReader中可能应该被视为错误的是它在声明它可以读取输入之前没有检查第一个块实际上是IHDR块。

您可以通过在其中一个您认为可以正常读取它们的查看器/应用程序中读取图像来修复图像,然后将它们作为普通PNG写回。我在OS X上使用Preview进行了测试,它运行良好。试一试。

如果在OS X上(使用开发工具),您还应该能够使用以下命令行使用Apple的修改后的pngcrush:

xcrun -sdk iphoneos pngcrush -revert-iphone-optimizations infile.png outfile.png

如果您只想获取图片的宽度/高度,则无需阅读完整的BufferedImages,只需获取ImageReader并使用其getWidth(0)和{{ 1}}方法(SO上有很多例子,不需要重复)。

您可能还可以创建一个快速PNG结构解析器,跳过getHeight(0)块,并直接解析CgBI,以获得宽度/高度。