ImageIO Неподдерживаемый тип изображения - плагин TwelveMonkeys с исправлением не работает?
Я обнаружил ошибку Unsupported Image Type из-за несовместимого цветового профиля, используя 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
Когда я запускаю свой код, он все еще пытается прочитать JPEG с com.sun.imageio.plugins.jpeg.JPEGImageReader
и продолжает бросать IIOException. Есть идеи?
ОБНОВЛЕНИЕ: похоже, что iTextPDF вызывает проблему, которая является библиотекой, используемой проектом. Я установил тестовое приложение barebone, которое конвертирует CMYK JPEG в BufferedImage
а потом звонит ImageIO.read(img)
и работает нормально. Я изо всех сил пытаюсь понять причину, по которой iText не может найти плагин TwelveMonkeys, когда он вызывает ImageIO.read(img)
когда они находятся в одном проекте и в классе, но это, вероятно, из-за моих ограниченных знаний. Я также должен добавить, что приложение, над которым я работаю, является частью API веб-службы.
2 ответа
Как часто бывает, когда плагин ImageIO не используется во время выполнения из веб-приложения, причина в том, что поставщик услуг не найден, потому что ImageIO
уже инициализирован и вызвал scanForPlugins()
до того, как библиотеки веб-приложения были доступны для JVM.
Из Развертывания плагинов [ImageIO] в веб-приложении:
Поскольку реестр плагинов ImageIO (
IIORegistry
) "VM global", по умолчанию он не работает с контекстами сервлета. Это особенно очевидно, если вы загружаете плагины изWEB-INF/lib
или жеclasses
папка. Если вы не добавитеImageIO.scanForPlugins()
где-то в вашем коде плагины могут вообще никогда не быть доступными.Кроме того, контексты сервлета динамически загружают и выгружают классы (используя новый загрузчик классов для каждого контекста). Если вы перезапустите приложение, старые классы по умолчанию останутся в памяти навсегда (потому что в следующий раз
scanForPlugins
называется, это другоеClassLoader
который сканирует / загружает классы, и, таким образом, они будут новыми экземплярами в реестре). Если попытка чтения выполняется с использованием одного из оставшихся "старых" считывателей, странные исключения (например,NullPointerExceptions
при доступе к статическим конечным инициализированным полям илиNoClassDefFoundErrors
для неинициализированных внутренних классов) может произойти.Чтобы обойти проблему обнаружения и утечку ресурсов, настоятельно рекомендуется использовать
IIOProviderContextListener
который реализует динамическую загрузку и выгрузку плагинов ImageIO для веб-приложений.
IIOProviderContextListener
содержится в twelvemonkeys-servlet.jar
и должен быть зарегистрирован в вашем приложении web.xml
(или подобное, если используется Spring или другой фреймворк). Смотрите выше ссылку для деталей.
Другой безопасной альтернативой использованию прослушивателя контекста является размещение файлов JAR в общей или общей папке lib сервера приложений вместо WEB-INF/lib
папка внутри вашего веб-приложения.
PS: вышеупомянутая проблема / решение относится к плагинам ImageIO в целом, а не только к плагинам TwelveMonkeys. Из-за этого прослушиватель контекста не имеет зависимостей от плагинов TwelveMonkeys ImageIO и может также использоваться с JAI ImageIO или другими плагинами ImageIO.
Для приложений Spring Boot, где нет web.xml, вам необходимо зарегистрировать
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);
}
Также см. Эту проблему, где это объясняется более подробно.