奇怪的 PNG 错误:IHDR 块的长度错误 [英] Strange PNG errors: Bad length for IHDR chunk

查看:33
本文介绍了奇怪的 PNG 错误:IHDR 块的长度错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

错误如下:

线程main"中的异常 javax.imageio.IIOException:读取 PNG 标头的 I/O 错误!在 com.sun.imageio.plugins.png.PNGImageReader.readHeader(PNGImageReader.java:307)在 com.sun.imageio.plugins.png.PNGImageReader.readMetadata(PNGImageReader.java:637)在 com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1212)在 com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1560)在 javax.imageio.ImageIO.read(ImageIO.java:1422)在 javax.imageio.ImageIO.read(ImageIO.java:1282)在 Bundle.iconExists(Bundle.java:139)在 Bundle.dPhIconExists(Bundle.java:158)在 BundleAnalyzer.supports6(BundleAnalyzer.java:14)在 TheifReader.(TheifReader.java:14)在 TheifReader.main(TheifReader.java:63)引起:javax.imageio.IIOException:IHDR 块的长度错误!在 com.sun.imageio.plugins.png.PNGImageReader.readHeader(PNGImageReader.java:239)……还有 10 个

这是导致它的代码:

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

icons 是一个文件数组.奇怪的是,我的计算机可以在任何图像查看器中正常读取图像.谷歌搜索错误没有给我任何结果.我有大量的图像需要阅读,那么除了将其转换为 BufferedImage 之外,它们是获取图像尺寸的另一种方法吗?这会解决问题吗?有没有办法修复这些图像?我是通过从 iOS 设备收集应用程序图标而得到它们的.来自我自己的设备的测试没有产生任何错误,尽管之前作为 zip 文件的一部分发送的测试虽然以相同的方式收集,但定期产生此错误.我所知道的关于压缩的一切都告诉我这不应该发生.我不知道从哪里开始寻找,真的需要修复.这是一个失败的示例图片.

我应该注意,对于我程序的这一部分,我只需要图像尺寸.我相信这可以通过阅读元数据来获得,但我也无法用 java 找到这方面的细节.

解决方案

根据 PNG 规范:

<块引用>

4.1.1.IHDR 图片标题

IHDR 块必须首先出现.

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

实际上,您的图片似乎是iOS 优化的 PNG".

来自 http://fileformats.archiveteam.org/wiki/CgBI:><块引用>

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

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

您可以修复图像,方法是在您认为可以正常阅读的查看器/应用程序之一中阅读它们,然后将它们作为普通 PNG 写回.我在 OS X 上使用 Preview 进行了测试,效果很好.试试看.

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

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


如果你只是想获取图片的宽度/高度,你不需要阅读完整的BufferedImages,只需获取一个ImageReader并使用它的getWidth(0)getHeight(0) 方法(已经有很多关于 SO 的示例,无需重复).

您可能还可以创建一个快速的 PNG 结构解析器,跳过 CgBI 块,直接解析 IHDR 以获得宽度/高度.

Heres the error:

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

and heres the code causing it:

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

icons is an array of files. The strange thing is that my computer can read the images just fine in any image viewer. Googling the error gave me no results. I have a ton of images I need to read, so is their an alternate way to get the dimensions of an image aside from turning it into a BufferedImage? Will that fix the problem? Is there a way to fix these images? I got them from collecting icons of apps from iOS devices. Tests from my own devices produced no errors, though ones that had previously been sent as part of a zip file, though gathered the same way, produced this error regularly. Everything I know about compression tells me this shouldn't happen. I am not sure where to begin looking, and really need a fix. Here is an example of a failed image.

I should note, for this part of my program, all I need are the image dimensions. I believe this can be obtained through reading metadata, but I also cannot find specifics on this with java.

解决方案

According to the PNG specifiaction:

4.1.1. IHDR Image header

The IHDR chunk must appear FIRST.

Your example image contains a custom critical chunk CgBI as the first chunk, and does not conform to this spec. This is why you get the exception.

Actually, it seems your image is an "iOS optimized PNG".

From http://fileformats.archiveteam.org/wiki/CgBI:

It is not compatible with PNG. Standard PNG decoders that don't support it will fail gracefully, due to an unknown "critical chunk".

Now, what probably should be considered a bug in the com.sun.imageio.plugins.png.PNGImageReader is that it doesn't check that the first chunk is actually a IHDRchunk, before claiming it can read the input.

You can fix the images, by reading them in one of the viewers/apps you say can read them fine, then writing them back as normal PNGs. I tested using Preview on OS X, and it worked fine. Give it a try.

If on OS X (with dev tools), you should also be able to use Apple's modified pngcrush with the following command line:

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


If you just want to get the width/height of the images, you don't need to read full BufferedImages, just get an ImageReader and use its getWidth(0) and getHeight(0) methods (there are plenty examples on SO for this already, no need to repeat).

You could probably also create a quick PNG structure parser, that skips the CgBI chunk, and parses the IHDR directly, to get width/height.

这篇关于奇怪的 PNG 错误:IHDR 块的长度错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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