I encountered the Unsupported Image Type error due to an incompatible colour profile using com.sun.imageio.plugins.jpeg.JPEGImageReader
. I later found the TwelveMonkeys plugins that are proven to fix this issue and have referenced the dependent .jars in my project classpath. I downloaded them from the TwelveMonkeys github repository. Note i'm using version 3.0.2 because I'm running on Java 6 with JDK 1.6.0_45. These are the .jars I've added to my project:
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
I was able to test the library is installed and working using the following test:
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
System.out.println("reader: " + readers.next());
}
Which outputs:
reader: com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader@4102799c
reader: com.sun.imageio.plugins.jpeg.JPEGImageReader@33d6f122
When i run my code, it is still trying to read the JPEG with com.sun.imageio.plugins.jpeg.JPEGImageReader
and continues to throw the IIOException. Any ideas?
UPDATE:
Its looking like iTextPDF is causing the issue which is a library used by the project. I setup a barebone test application that converts a CMYK JPEG to a BufferedImage
and then calls ImageIO.read(img)
and it works fine. I'm struggling to see a reason why iText wouldn't be finding the TwelveMonkeys plugin when it calls ImageIO.read(img)
when they're in the same project and classpath, but that's probably due to my limited knowledge. I should also add that the application i'm working on is part of a web service API.
As often is the case, when an ImageIO plugin isn't used at run-time from a web application, the cause is that the service provider isn't found because ImageIO
is already initialized, and has invoked scanForPlugins()
before the web app's libraries were available to the JVM.
From 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.
The IIOProviderContextListener
is contained in the twelvemonkeys-servlet.jar
, and must be registered in your application's web.xml
(or similar if using Spring or other framework). See the above link for details.
Another safe alternative to using the context listener, is to place the JAR files in the application server's shared or common lib folder, instead of the WEB-INF/lib
folder inside your web application.
PS: The above problem/solution applies to ImageIO plugins in general, not just the TwelveMonkeys plugins. Because of this, the context listener has no dependencies to the TwelveMonkeys ImageIO plugins, and may be used with JAI ImageIO or other ImageIO plugins as well.