Чистая альтернатива Java для JAI ImageIO для обнаружения изображений CMYK

Сначала я хотел бы объяснить ситуацию / требования, которые приводят к вопросу:

В нашем веб-приложении мы не можем поддерживать изображения CMYK (JPEG), поскольку IE 8 и ниже не может их отображать. Таким образом, нам нужно определить, когда кто-то хочет загрузить такое изображение, и отклонить это.

К сожалению, Java ImageIO не читает эти изображения или не позволяет мне получить обнаруженное цветовое пространство. Из-за отладки кажется, что JPEGImageReader внутренне получает код цветового пространства 11 (что означает JCS_YCCK), но я не могу безопасно получить доступ к этой информации.

Запрашивая у читателя типы изображений, я ничего не получаю для CMYK, поэтому могу предположить no image types = unsupported image.

Я преобразовал исходное изображение CMYK в RGB с помощью инструмента обработки изображений, чтобы проверить, будет ли оно читаемым (я попытался смоделировать действия администратора при получении сообщения «Нет поддержки CMYK»). Однако JPEGImageReader не будет читать это изображение, поскольку оно предполагает (комментарий в источнике!) 3-компонентное цветовое пространство RGB, но заголовок изображения сообщает о 4 компонентах (возможно, RGBA или ARGB), и, таким образом, IllegalArgumentException является брошен.

Таким образом, ImageIO не является вариантом, поскольку я не могу надежно получить цветовое пространство изображения и не могу сказать администратору, почему в противном случае прекрасное изображение (оно может отображаться браузером) не будет принято из-за некоторых внутренних ошибка.

Это побудило меня попробовать JAI ImageIO, CLibJPEGImageReader которого отлично справляется и правильно читает все мои тестовые изображения.

Однако, поскольку мы развертываем наше приложение в JBoss, на котором могут размещаться и другие приложения, мы хотели бы сохранить их как можно более изолированными. AFAIK, мне нужно установить JAI ImageIO в JRE или иным образом сделать доступными собственные библиотеки, чтобы использовать их, и, таким образом, другие приложения также могут получить к ним доступ, что может вызвать побочные эффекты (по крайней мере, у нас были бы много проверять, чтобы убедиться, что это не так).

Это объяснение вопроса, и вот оно снова: Есть ли чистая альтернатива Java JAI ImageIO, которая надежно обнаруживает и, возможно, конвертирует изображения CMYK?

Заранее спасибо,

Томас


person Thomas    schedule 26.07.2011    source источник


Ответы (4)


Я нашел решение, которое подходит для наших нужд: Apache Commons Sanselan. Эта библиотека довольно быстро и точно считывает заголовки JPEG (по крайней мере, все мои тестовые изображения), а также ряд других форматов изображений.

Обратной стороной является то, что он не будет читать данные изображения JPEG, но я могу сделать это с помощью основных инструментов JRE.

Считывать изображения JPEG для преобразования довольно просто (те, которые ImageIO тоже отказываются читать):

JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream( new File(pFilename) ) );
BufferedImage sourceImg = decoder.decodeAsBufferedImage();

Затем, если Санселан говорит мне, что изображение на самом деле CMYK, я получаю растр исходного изображения и конвертирую себя:

for( /*each pixel in the raster, which is represented as int[4]*/ )
{  
   double k = pixel[3] / 255.0;

   double r = (255.0 - pixel[0])*k;
   double g = (255.0 - pixel[1])*k;
   double b = (255.0 - pixel[2])*k;
}

Это дает неплохие результаты, когда изображения RGB не слишком яркие или темные. Однако я не уверен, почему умножение на k предотвращает осветление. JPEG фактически декодируется в собственном коде, а преобразование CMYK-> RGB, которое я получил, говорит о другом, я просто попробовал умножить, чтобы увидеть визуальный результат.

Если бы кто-нибудь мог пролить свет на это, я был бы признателен.

person Thomas    schedule 01.08.2011
comment
Я столкнулся с той же проблемой с изображениями JAI и CMYK JPEG. Вы уже используете этот подход в производстве? Как твой опыт? Думаю, вы используете Sanselan.getImageInfo(...).getColorType() == ImageInfo.COLOR_TYPE_CMYK (ImageInfo) чтобы проверить, является ли изображение CMYK, верно? - person Benedikt Waldvogel; 17.11.2011
comment
@bene Да, мы сначала проверяем, нашел ли Sanselan профиль ICC, и если да, то берем его тип цветового пространства, но если это не удается, мы используем ImageInfo.getColorType(). Мы используем это в продакшене, и пока у нас не было никаких проблем, однако я должен признать, что в настоящее время мы не обрабатываем много изображений. В будущем у нас будет собственная база данных мультимедиа, которая будет обрабатывать тысячи изображений, и тогда у нас будет более надежная информация о готовности такого подхода к производству. Только одно замечание: преобразование CMYK Tiffs дает заметные оттенки, и нам пока не удалось от них избавиться. - person Thomas; 17.11.2011
comment
Сегодня я наткнулся на изображение, где в ICCProfile Санселана используется ColorSpaceType CMYK, а в ImageInfo ColorType - RGB. Цветовое пространство на самом деле RGB. Интересно, была ли у вас такая же проблема. - person Benedikt Waldvogel; 07.02.2012
comment
@bene У нас пока не было такой проблемы, но я мог бы взглянуть на наши источники и на санселановые. Возможно, у кого-то была эта проблема без моего ведома и он адаптировал наш код. Меня тоже заинтересует это изображение, не могли бы вы опубликовать ссылку на него? - person Thomas; 07.02.2012
comment
Например, этот: images.internetstores.de/products/ - person Benedikt Waldvogel; 08.02.2012

Я опубликовал решение на чистом Java для чтения всех видов изображений JPEG и преобразования их в RGB.

Он основан на следующих фактах:

  • Хотя ImageIO не может читать изображения JPEG с CMYK в качестве буферизованного изображения, он может читать необработанные данные пикселей (растр).
  • Sanselan (или Apache Commons Imaging, как его сейчас называют) можно использовать для чтения деталей изображений CMYK.
  • Есть изображения с перевернутыми значениями CMYK (старая ошибка Photoshop).
  • Есть изображения с YCCK вместо CMYK (легко конвертируются).
person Codo    schedule 26.08.2012

Остерегайтесь другого сообщения, поскольку Java 7 не позволяет напрямую использовать реализацию Sun без специальных параметров, как указано в импортировать com.sun.image.codec.jpeg. *.

person tsmets    schedule 10.01.2014

В нашем веб-приложении мы не можем поддерживать изображения CMYK (JPEG), поскольку IE 8 и ниже не может их отображать. Таким образом, нам нужно определить, когда кто-то хочет загрузить такое изображение, и отклонить это.

Я не согласен с вашим «Таким образом, нам нужно определить, когда кто-то хочет загрузить такое изображение, и отклонить это». Гораздо более удобной политикой было бы преобразование его во что-то еще, кроме CMYK.

Остальная часть вашего сообщения немного сбивает с толку, поскольку вы видите, что вы запрашиваете и обнаружение, и преобразование, а это две разные вещи. Еще раз, я считаю, что преобразование изображения намного удобнее.

Не нужно писать жирным шрифтом btw:

Есть ли альтернатива JAI ImageIO на чистом Java, которая надежно обнаруживает и, возможно, конвертирует изображения CMYK?

Чистая Java, я не знаю, но ImageMagick отлично работает для преобразования изображений CMYK в изображения RGB. Вызвать ImageMagick на стороне сервера из Java действительно несложно. Раньше я делал это вручную, вызывая внешний процесс, но в настоящее время есть оболочки, такие как JMagick и im4java.

person SyntaxT3rr0r    schedule 26.07.2011
comment
Что касается удобства для пользователя: преобразование CMYK в RGB иногда немного осветляет цвета, и поэтому мы хотели бы, чтобы пользователь преобразовал его вручную и подтвердил, что цвета все еще в порядке. В другом приложении мы можем конвертировать независимо от этого, поэтому я попросил и то, и другое. - person Thomas; 26.07.2011
comment
No need to write in bold btw: - это было просто, чтобы отметить вопрос для тех, кто не хочет читать беспорядок между ними :) - person Thomas; 26.07.2011
comment
Относительно ImageMagick: это может быть альтернативой, хотя нам также необходимо установить его. Спасибо за это предложение. - person Thomas; 26.07.2011