【问题标题】:ImageIO throws IIOException for 60x45, 0.5MB - JPEG Image File during ReadingImageIO 为 60x45、0.5MB 引发 IIOException - 读取期间的 JPEG 图像文件
【发布时间】:2013-10-30 03:57:07
【问题描述】:

我有一个奇怪的 JPEG 图像文件,ImageIO.read() 无法加载:

ImageIO.read(new URL("http://nocturne.wmw.cc/a.jpg"));

有什么想法吗?

Exception in thread "main" javax.imageio.IIOException: Unsupported Image Type
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:995)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:966)
    at javax.imageio.ImageIO.read(ImageIO.java:1448)
    at javax.imageio.ImageIO.read(ImageIO.java:1400)
    at Main.main(Main.java:23)

imageurl

【问题讨论】:

  • 它为我抛出"Incompatible color conversion",可能图像包含错误,我不知道为什么 FireFox 可以打开它(也许是魔法!)但图像大小有点大! 500KB 对于一个非常小的图像来说太大了!哇!它是否包含任何嵌入数据?
  • 哈!这就是我喜欢通过 Java 分析的——嵌入式数据!也许某种证书?这是一个名为 Stiftung Warentest 的大型官方组织,是一个消费者保护机构。
  • 嗯,因此您可能需要手动操作流,并将图像数据与嵌入数据分开。但我建议使用本机代码 C/C++ 来做这些事情……Ta Ta

标签: java image metadata


【解决方案1】:

好吧...我花了一段时间才发现这个问题...问题出在图像本身,它有一个 CMYK 颜色配置文件(即 Coated FOGRA27),混淆了 java 中的 JPEG 阅读库。

在 Photoshop 中打开图像会生成 CMYK 颜色模式的图像(至少对我而言),这似乎不受 java 支持。将颜色模式更改为 RGB 并使用 sRGB 颜色配置文件保存允许 ImageIO 库成功读取图像。

ImageIO 库仅实现可读颜色配置文件的子集,不处理没有任何配置文件的图像。

进一步阅读 JPEGImageReader 源代码得到以下代码:

switch (colorSpaceCode) {
    case JPEG.JCS_GRAYSCALE:
        list.add(raw);
        list.add(getImageType(JPEG.JCS_RGB));
        break;
    case JPEG.JCS_RGB:
        list.add(raw);
        list.add(getImageType(JPEG.JCS_GRAYSCALE));
        list.add(getImageType(JPEG.JCS_YCC));
        break;
    case JPEG.JCS_RGBA:
        list.add(raw);
        break;
    case JPEG.JCS_YCC:
        if (raw != null) {  // Might be null if PYCC.pf not installed
            list.add(raw);
            list.add(getImageType(JPEG.JCS_RGB));
        }
        break;
    case JPEG.JCS_YCCA:
        if (raw != null) {  // Might be null if PYCC.pf not installed
            list.add(raw);
        }
        break;
    case JPEG.JCS_YCbCr:
        // As there is no YCbCr ColorSpace, we can't support
        // the raw type.

        // due to 4705399, use RGB as default in order to avoid
        // slowing down of drawing operations with result image.
        list.add(getImageType(JPEG.JCS_RGB));

        if (iccCS != null) {
            list.add(new ImageTypeProducer() {
                protected ImageTypeSpecifier produce() {
                    return ImageTypeSpecifier.createInterleaved
                     (iccCS,
                      JPEG.bOffsRGB,  // Assume it's for RGB
                      DataBuffer.TYPE_BYTE,
                      false,
                      false);
                }
            });

        }

        list.add(getImageType(JPEG.JCS_GRAYSCALE));
        list.add(getImageType(JPEG.JCS_YCC));
        break;
    case JPEG.JCS_YCbCrA:  // Default is to convert to RGBA
        // As there is no YCbCr ColorSpace, we can't support
        // the raw type.
        list.add(getImageType(JPEG.JCS_RGBA));
        break;
}

异常的来源:

Iterator imageTypes = getImageTypes(imageIndex);
if (imageTypes.hasNext() == false) {
    throw new IIOException("Unsupported Image Type");
}

如您所见,当 JPEG 图像的颜色配置文件未在 switch 语句中列出时,不会将任何内容添加到“list”变量中,该变量最终会传递给第二段代码中的特定迭代器。对于空列表,Iterator.hasNext() 方法返回 false,抛出异常。

【讨论】:

  • 哇,伙计,我很欣赏这项工作,但我得说这有点像陷阱伙计,图像包含嵌入数据。
  • @user2511414 嗯...制作图像的人应该包含颜色配置文件,最好是 sRGB...您可以编写自己的 JPEG 阅读库来处理此类特殊情况,或者找到一些可以为你做这件事。
  • 嗯,这100%解决了这个问题,但是嵌入数据呢?
  • 好朋友,使用 BufferedImage 和默认颜色模式 (sRGB) 创建一个空图像怎么样。然后尝试从 url 读取数据并逐像素设置图像数据。我不知道它是否有效,但可能
  • @PeterRader 在这里查看我的答案for a CMYK capable JPEGImageReader for ImageIO
猜你喜欢
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多