ImageIO 不支持的图像类型 - 修复后的 TwelveMonkeys 插件不起作用?
ImageIO Unsupported Image Type - TwelveMonkeys Plugin with fix not working?
由于使用 com.sun.imageio.plugins.jpeg.JPEGImageReader
的颜色配置文件不兼容,我遇到了不支持的图像类型错误。后来我发现 TwelveMonkeys 插件被证明可以解决这个问题,并在我的项目类路径中引用了相关的 .jars。我从 TwelveMonkeys github 存储库下载了它们。请注意,我使用的是 3.0.2 版,因为我 运行 在 Java 6 上使用 JDK 1.6.0_45。这些是我添加到项目中的 .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。
通常情况下,当网络应用程序 run-time 未使用 ImageIO 插件时,原因是找不到服务提供者,因为 ImageIO
已经初始化,并在 Web 应用程序的库可用于 JVM 之前调用了 scanForPlugins()
。
来自 Deploying [ImageIO] plugins in a web app:
Because the ImageIO plugin registry (the IIORegistry
) is "VM global", it doesn't by default work well with servlet contexts. This is especially evident if you load plugins from the WEB-INF/lib
or classes
folder. Unless you add ImageIO.scanForPlugins()
somewhere in your code, the plugins might never be available at all.
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context). If you restart your application, old classes will by default remain in memory forever (because the next time scanForPlugins
is called, it's another ClassLoader
that scans/loads classes, and thus they will be new instances in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions (like NullPointerExceptions
when accessing static final initialized fields or NoClassDefFoundErrors
for uninitialized inner classes) may occur.
To work around both the discovery problem and the resource leak, it is strongly recommended to use the IIOProviderContextListener
that implements dynamic loading and unloading of ImageIO plugins for web applications.
IIOProviderContextListener
包含在 twelvemonkeys-servlet.jar
中,并且必须在您的应用程序的 web.xml
中注册(如果使用 Spring 或其他框架,则类似)。详见上文link
使用上下文侦听器的另一个安全替代方法是将 JAR 文件放在应用程序服务器的共享或公共 lib 文件夹中,而不是 Web 应用程序中的 WEB-INF/lib
文件夹。
PS:以上problem/solution一般适用于ImageIO插件,而不仅仅是TwelveMonkeys插件。因此,上下文侦听器不依赖于 TwelveMonkeys ImageIO 插件,也可以与 JAI ImageIO 或其他 ImageIO 插件一起使用。
对于 Spring 没有 web.xml 的引导应用程序,您需要在 @SpringBootApplication
class 中注册 IIOProviderContextListener
,它应该扩展 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,其中对此进行了更详细的解释。
由于使用 com.sun.imageio.plugins.jpeg.JPEGImageReader
的颜色配置文件不兼容,我遇到了不支持的图像类型错误。后来我发现 TwelveMonkeys 插件被证明可以解决这个问题,并在我的项目类路径中引用了相关的 .jars。我从 TwelveMonkeys github 存储库下载了它们。请注意,我使用的是 3.0.2 版,因为我 运行 在 Java 6 上使用 JDK 1.6.0_45。这些是我添加到项目中的 .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。
通常情况下,当网络应用程序 run-time 未使用 ImageIO 插件时,原因是找不到服务提供者,因为 ImageIO
已经初始化,并在 Web 应用程序的库可用于 JVM 之前调用了 scanForPlugins()
。
来自 Deploying [ImageIO] plugins in a web app:
Because the ImageIO plugin registry (the
IIORegistry
) is "VM global", it doesn't by default work well with servlet contexts. This is especially evident if you load plugins from theWEB-INF/lib
orclasses
folder. Unless you addImageIO.scanForPlugins()
somewhere in your code, the plugins might never be available at all.In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context). If you restart your application, old classes will by default remain in memory forever (because the next time
scanForPlugins
is called, it's anotherClassLoader
that scans/loads classes, and thus they will be new instances in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions (likeNullPointerExceptions
when accessing static final initialized fields orNoClassDefFoundErrors
for uninitialized inner classes) may occur.To work around both the discovery problem and the resource leak, it is strongly recommended to use the
IIOProviderContextListener
that implements dynamic loading and unloading of ImageIO plugins for web applications.
IIOProviderContextListener
包含在 twelvemonkeys-servlet.jar
中,并且必须在您的应用程序的 web.xml
中注册(如果使用 Spring 或其他框架,则类似)。详见上文link
使用上下文侦听器的另一个安全替代方法是将 JAR 文件放在应用程序服务器的共享或公共 lib 文件夹中,而不是 Web 应用程序中的 WEB-INF/lib
文件夹。
PS:以上problem/solution一般适用于ImageIO插件,而不仅仅是TwelveMonkeys插件。因此,上下文侦听器不依赖于 TwelveMonkeys ImageIO 插件,也可以与 JAI ImageIO 或其他 ImageIO 插件一起使用。
对于 Spring 没有 web.xml 的引导应用程序,您需要在 @SpringBootApplication
class 中注册 IIOProviderContextListener
,它应该扩展 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,其中对此进行了更详细的解释。