【问题标题】:Java ImageIO IIOException: Unsupported image type?Java ImageIO IIOException:不支持的图像类型?
【发布时间】:2011-11-02 21:47:28
【问题描述】:

第一次在 Java 中使用图像,并且遇到了一些没有很好记录的奇怪异常。这是失败的代码行:

BufferedImage imgSelected = ImageIO.read(new File("/abs/url/to/file/image.jpg"));

这行抛出了一个带有不支持的图像类型 的 IIOException 作为异常消息。我已经检查并重新检查了实际上是这一行引发了异常,File 对象有效,URL 有效,并且 image.jpg 实际上是一个有效的 JPG,在其他图像中加载得非常好观众。

如何获得有关此异常性质的更多信息?这是在 Java 7 中加载图像的传统方式,还是一种旧的/不推荐使用的方法?关于这些“不受支持的图像类型”异常的信息并不多,而且 ImageIO 肯定支持 JPG!

感谢您的帮助!

【问题讨论】:

    标签: java image exception javax.imageio


    【解决方案1】:

    尝试检查 JPEG 的编码。例如,ImageIO 无法读取 CMYK 编码的 jpeg 图像。 AFAIK,ImageIO 多年未更新,因此您想尝试使用官方替代/扩展:JAI ImageIO

    不幸的是,JAI ImageIO 需要在 JRE 中安装一些本机库,这可能是不需要的。 我们执行以下操作:

    • 使用Apache Sanselan检测是否为JPEG格式
    • 由于 Sanselan 无法读写 JPEG,所以使用普通的旧 AWT JPEGCodec:JPEGCodec.createJPEGDecoder(...)
    • 要将 CMYK 转换为 RGB,然后我们获取读取的光栅 BufferedImage 并手动转换(您可以使用 ICC 配置文件,但手动转换符合我们的需要)

    这是我的一个问题,原因是 ImageIO 不支持所有类型的 JPEG 图像,我在那里陈述了我对您收到该消息的原因的更多发现:Pure Java alternative to JAI ImageIO for detecting CMYK images

    【讨论】:

    • 这里的问题当然是 JAI ImageIO 的原生库(至少在 Windows 上)只支持 32 位。
    【解决方案2】:

    不幸的是,我遇到了很多违反标准的 JPEG 文件。 ImageIO 尤其挑剔,经常拒绝加载图像,这些图像通常被其他对文件格式检查不那么严格的软件加载并明显正确显示。

    这不是很漂亮,但一种解决方法是直接使用 Oracle VM 内部 JPEG 解码器 (com.sun.image.codec.jpeg.JPEGCodec),因为它似乎可以容忍更多的规格偏差作为 ImageIO 包装器:

    BufferedImage img = 
        JPEGCodec.createJPEGDecoder(inputStream).decodeAsBufferedImage();
    

    这当然不是一个理想的解决方案,因为使用特定于实现的类会将您锁定到特定的 VM 供应商,并且可能会与较新的 VM 版本中断,但如果您只在受控环境中使用该软件,则可能总比没有解决好。

    【讨论】:

    • 这是一个很好的建议@jarnbjo。感谢您花时间回答我的问题,绝对值得深思。
    • 我已经在 cmyk 图像上进行了尝试,导致出现主题中的异常并且失败(java 版本“1.8.0_60”):com.sun.image.codec.jpeg.ImageFormatException:不是 JPEG 文件:在 sun.awt.image.codec.JPEGImageDecoderImpl.readJPEGStream(Native Method) ~[?:1.8.0_60] 处以 0xce 0x08 开头
    【解决方案3】:

    要处理特定格式的图像,您需要添加相应的依赖项,例如 imageio-jpeg 或 imageio-tiff:

    <dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-jpeg</artifactId>
    <version>3.3.2</version>
    </dependency>
    
    <dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-bmp</artifactId>
    <version>3.3.2</version>
    </dependency>
    
    <dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-core</artifactId>
    <version>3.3.2</version>
    </dependency>
    

    内置的 ImageIO Java API 在运行时自动加载插件。

    【讨论】:

    • 刚刚尝试了一个我无法用 ImageIO 读取的 Photoshop-jpg 文件(到目前为止)。 Twelvemonkeys 开箱即用,我可以读取有问题的文件。只是添加了依赖项,仅此而已(我不知道 Twelvemonkeys 是如何做到的——但它似乎做得很好)。您不必包含 imageio-core。对 imageio-jpeg 的依赖就足够了(对于 jpeg 文件),其余的由 maven 完成。 Twelvemonkey 似乎支持更多的文件类型(参见github.com/haraldk/TwelveMonkeys 的列表)。
    【解决方案4】:

    另一种选择是使用 Werner Randelshofer 准备的 .jar:

    http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/ 或 Monte 媒体库:http://www.randelshofer.ch/monte/

    它看起来很简单,类似于 ImageIO 的使用,并且在 CC 许可下可用。

    【讨论】:

    • 但它也使用JVM内部类,如:com.sun.imageio.plugins.jpeg.JPEGImageReader
    【解决方案5】:

    这个tutorial provided 是一个使用 apache commons IO 库的答案。我发现它是一个更干净的实现。我在下面包含了依赖项

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.11.0</version>
    </dependency>
    

    这是添加依赖后工作的代码

        public ResponseEntity<byte[]> getImage(@PathVariable("filename") String filename) {
         byte[] image = new byte[0];
          try {
              image = FileUtils.readFileToByteArray(new File(FILE_PATH_ROOT+filename));
          } catch (IOException e) {
              e.printStackTrace();
          }
          return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(image);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多