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);
    }

Также см. Эту проблему, где это объясняется более подробно.

Другие вопросы по тегам