ArrayIndexOutOfBoundsException:读取 gif 文件时出现 4096

Posted

技术标签:

【中文标题】ArrayIndexOutOfBoundsException:读取 gif 文件时出现 4096【英文标题】:ArrayIndexOutOfBoundsException: 4096 while reading gif file 【发布时间】:2014-04-11 04:02:29 【问题描述】:

我可以读取 png 文件。但是在读取 gif 文件时得到 ArrayIndexOutOfBoundsException: 4096。

byte[] fileData = imageFile.getFileData();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData);
RenderedImage image = ImageIO.read(byteArrayInputStream)

抛出的异常看起来像

java.lang.ArrayIndexOutOfBoundsException: 4096
    at com.sun.imageio.plugins.gif.GIFImageReader.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)

可能是什么问题,解决方法是什么?

【问题讨论】:

您尝试阅读的每个 gif 是否都会发生这种情况,还是仅特定的 gif 会发生这种情况 这几乎发生在我所有的 gif 中。 你能提供其中一个 GIF 吗? 您可能有损坏的.gif 文件(例如太短/尚未完全传输左右)或ImageIO 无法理解的 gif 类型。 这显然是内部 GIFImageReader 的错误,从未得到修复。 【参考方案1】:

更新 3:解决方案

我最终开发了自己的 GifDecoder,并在 Apache 许可证 2.0 下将其作为开源发布。你可以从这里得到它:https://github.com/DhyanB/Open-Imaging。它不受ArrayIndexOutOfBoundsException 问题的影响,并提供了不错的性能。

非常感谢任何反馈。特别是,我想知道它是否适用于您的所有图像,以及您是否对它的速度感到满意。

希望对你有帮助(:

初步回答

也许此错误报告与或描述相同的问题:https://bugs.openjdk.java.net/browse/JDK-7132728。

引用:

完整产品版本:
java版本“1.7.0_02”
Java(TM) SE 运行时环境 (build 1.7.0_02-b13)
Java HotSpot(TM) 64 位服务器 VM(内部版本 22.0-b10,混合模式)

其他操作系统版本信息:
Microsoft Windows [版本 6.1.7601]

问题描述:
根据规范
http://www.w3.org/Graphics/GIF/spec-gif89a.txt
> 字符串表已满时无需发送明码。

但是,GIFImageReader 在字符串表已满时需要清除代码。
GIFImageReader 显然违反了规范。
在现实世界中,有时人们会发现如此高压缩的 gif 图像。
所以你应该修复这个错误。

重现问题的步骤:
javac -cp .;PATH_TO_COMMONS_CODEC GIF_OverflowStringList_Test.java
java -cp .;PATH_TO_COMMONS_CODEC GIF_OverflowStringList_Test

预期与实际行为:
预期的 -
正常完成。没有输出
实际的 -
ArrayIndexOutOfBounds 发生。

发生的错误消息/堆栈跟踪:
线程“主”java.lang.ArrayIndexOutOfBoundsException 中的异常:4096
        在 com.sun.imageio.plugins.gif.GIFImageReader.read(GIFImageReader.java:1
075)
        在 javax.imageio.ImageIO.read(ImageIO.java:1400)
        在 javax.imageio.ImageIO.read(ImageIO.java:1322)
        在 GIF_OverflowStringList_Test.main(GI​​F_OverflowStringList_Test.java:8)


再现性:
这个错误总是可以重现的。

错误报告还提供了重现错误的代码。

更新 1

这是导致我自己代码中的错误的图像:

更新 2

我尝试使用 Apache Commons Imaging 读取相同的图像,导致以下异常:

java.io.IOException: AddStringToTable: 代码: 4096 code_size: 12
    在 org.apache.commons.imaging.common.mylzw.MyLzwDecompressor.addStringToTable(MyLzwDecompressor.java:112)
    在 org.apache.commons.imaging.common.mylzw.MyLzwDecompressor.decompress(MyLzwDecompressor.java:168)
    在 org.apache.commons.imaging.formats.gif.GifImageParser.readImageDescriptor(GifImageParser.java:388)
    在 org.apache.commons.imaging.formats.gif.GifImageParser.readBlocks(GifImageParser.java:251)
    在 org.apache.commons.imaging.formats.gif.GifImageParser.readFile(GifImageParser.java:455)
    在 org.apache.commons.imaging.formats.gif.GifImageParser.readFile(GifImageParser.java:435)
    在 org.apache.commons.imaging.formats.gif.GifImageParser.getBufferedImage(GifImageParser.java:646)
    在 org.apache.commons.imaging.Imaging.getBufferedImage(Imaging.java:1378)
    在 org.apache.commons.imaging.Imaging.getBufferedImage(Imaging.java:1292)

这看起来与我们在 ImageIO 中遇到的问题非常相似,因此我在 Apache Commons JIRA 上报告了该错误:https://issues.apache.org/jira/browse/IMAGING-130。

【讨论】:

哇,这太疯狂了,他们这么久都没有修好。 这里是JDK 1.8.0_45 ... bug 仍然存在:\ 我最近遇到了一个类似的bug。第 11 帧出现越界异常。 很好的解释。感谢您提供测试图像。这个 SO 答案在 IMAGING-130 中链接,另一个贡献者提交了一个已经合并的拉取请求。此修复程序将在 commons-imaging-1.0-alpha2 版本中提供。谢谢!布鲁诺【参考方案2】:

我遇到了与您完全相同的问题,但我必须坚持使用 ImageIO 接口,这是其他库所没有的。除了 Jack 的出色回答之外,我只是用几行代码修补了现有的 GIFImageReader 类,并让它勉强工作。

将this link 复制到PatchedGIFImageReader.java 并照此使用:

reader = new PatchedGIFImageReader(null);
reader.setInput(ImageIO.createImageInputStream(new FileInputStream(files[i])));
int ub = reader.getNumImages(true);
for (int x=0;x<ub;x++) 
    BufferedImage img = reader.read(x);
    //Do whatever with the new img bufferedimage

请务必将包名称更改为您正在使用的任何名称。

不幸的是,结果可能会有所不同,因为补丁是一个 1 分钟的错误修复,如果它超过缓冲区,基本上只会退出循环。有些 gif 加载良好,有些则有一些视觉伪影。

这就是生活。如果有人知道比我更好的解决方法,请告诉我。

【讨论】:

以上是关于ArrayIndexOutOfBoundsException:读取 gif 文件时出现 4096的主要内容,如果未能解决你的问题,请参考以下文章