ImageIO不支持的图像类型 - 修复不起作用的TwelveMonkeys插件?

时间:2018-03-14 05:34:32

标签: java compression javax.imageio twelvemonkeys

由于使用com.sun.imageio.plugins.jpeg.JPEGImageReader的颜色配置文件不兼容,我遇到了“不支持的图像类型”错误。我后来发现TwelveMonkeys插件已被证明可以解决这个问题并在我的项目类路径中引用了依赖的.jars。我从TwelveMonkeys github存储库下载了它们。请注意我使用的是3.0.2版本,因为我使用JDK 1.6.0_45在Java 6上运行。这些是我添加到项目中的.jars:

common-lang-3.0.2.jar
common-io-3.0.2.jar
common-image-3.0.2.jar
imageio-core-3.0.2.jar
imageio-metadata-3.0.2.jar
imageio-jpeg-3.0.2.jar

我能够使用以下测试来测试库的安装和工作:

Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
    System.out.println("reader: " + readers.next());
}

哪个输出:

reader: com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader@4102799c
reader: com.sun.imageio.plugins.jpeg.JPEGImageReader@33d6f122

当我运行我的代码时,它仍然试图用com.sun.imageio.plugins.jpeg.JPEGImageReader读取JPEG并继续抛出IIOException。有什么想法吗?

更新: 它看起来像iTextPDF导致问题,这是项目使用的库。我设置了一个准系统测试应用程序,将CMYK JPEG转换为BufferedImage,然后调用ImageIO.read(img),它运行正常。我很难看到当iText在同一项目和类路径中调用ImageIO.read(img)时找不到TwelveMonkeys插件的原因,但这可能是由于我的知识有限。我还要补充一点,我正在处理的应用程序是Web服务API的一部分。

2 个答案:

答案 0 :(得分:1)

通常情况下,如果在运行时没有从Web应用程序使用ImageIO插件,原因是找不到服务提供商,因为ImageIO已经初始化,并且在Web应用程序的库可用于JVM之前调用了scanForPlugins()

来自Deploying [ImageIO] plugins in a web app

  

因为ImageIO插件注册表(IIORegistry)是&#34; VM global&#34;,它默认不适用于servlet上下文。如果您从WEB-INF/libclasses文件夹加载插件,这一点尤其明显。除非您在代码中的某处添加ImageIO.scanForPlugins(),否则插件可能永远不可用。

     

此外,servlet上下文动态地加载和卸载类(每个上下文使用一个新的类加载器)。如果重新启动应用程序,默认情况下旧类将永远保留在内存中(因为下次调用scanForPlugins时,它会扫描/加载类的另一个ClassLoader,因此它们将是注册表中的新实例)。如果尝试使用剩余的&#34; old&#34;之一进行读取。读者,奇怪的异常(例如访问静态最终初始化字段时为NullPointerExceptions或未初始化内部类可能出现NoClassDefFoundErrors)。

     

要解决发现问题和资源泄漏问题,强烈建议使用IIOProviderContextListener实现动态加载和卸载Web应用程序的ImageIO插件。

IIOProviderContextListener包含在twelvemonkeys-servlet.jar中,必须在您的应用程序web.xml中注册(如果使用Spring或其他框架,则必须注册)。有关详细信息,请参阅上面的链接。

使用上下文侦听器的另一个安全替代方法是将JAR文件放在应用程序服务器的共享或公共lib文件夹中,而不是放在Web应用程序中的WEB-INF/lib文件夹中。

PS:上述问题/解决方案通常适用于ImageIO插件,而不仅仅适用于TwelveMonkeys插件。因此,上下文侦听器与TwelveMonkeys ImageIO插件没有依赖关系,也可以与JAI ImageIO或其他ImageIO插件一起使用。

答案 1 :(得分:0)

对于没有 web.xml 的 Spring Boot 应用程序,您需要在应该扩展 IIOProviderContextListener@SpringBootApplication 类中注册 SpringBootServletInitializer

@Override
    public void onStartup(final ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        // Register the listener from Twelvemonkeys to support CMYK image handling with ImageIO
        servletContext.addListener(IIOProviderContextListener.class);
    }

另请参阅 this issue 更详细的解释。