Могу ли я использовать libjpeg для чтения JPEG с альфа-каналом? - PullRequest
10 голосов
/ 02 июня 2011

Похоже, есть некоторые споры о том, являются ли JPEG с альфа-каналами действительными или нет. Ответ, который я всегда понимал, чтобы быть правильным, это , что в FAQ по JPEG , что по сути "Нет". (Это повторяется в другом вопросе о переполнении стека .)

Тем не менее, Java JPEGImageWriter в библиотеке Sun ImageIO от Sun с радостью будет писать и читать изображения в градациях серого и RGB с альфа-каналом, хотя в Linux я практически не пробовал приложений, которые бы правильно загружали такие JPEG-файлы. В прошлом об этом сообщалось как об ошибке, но Sun ответила, что это действительные файлы :

Это не ошибка ввода-вывода изображения, а скорее недостаток в других приложениях податель упоминает. IIO JPEGImageWriter может записывать изображения с цветовая модель, которая содержит альфа-канал (упоминается в нативном IJG исходный код в виде цветовых пространств "NIFTY", таких как RGBA, YCbCrA и т. д.), но многие приложения не знают об этих цветовых пространствах. Так что, хотя эти изображения написанные автором IIO JPEG соответствуют спецификации JPEG (которая не учитывает различные возможности цветового пространства), некоторые приложения могут не распознавать цветовые пространства, которые содержат альфа-канал и могут генерировать ошибка или визуализация поврежденного изображения, как описывает отправитель.

Разработчики, желающие поддерживать совместимость с этими другими альфа-программами приложения должны писать изображения, которые не содержат альфа-канал (например, TYPE_INT_RGB). Разработчики, которые хотят иметь возможность писать / читать изображения содержащий альфа-канал в формате JPEG, можно сделать это с помощью Image I / O API, но нужно знать, что многие родные приложения там не совсем совместим с форматами YCbCrA и RGBA.

Для получения дополнительной информации см. Спецификацию формата метаданных JPEG I / O JPEG и Примечания по использованию: http://java.sun.com/j2se/1.4.1/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html

Закрытие как "не ошибка". ххххх @ ххххх 2003-03-24

Я работаю с приложением Java, которое создает подобные файлы, и хочу написать код на C, который будет загружать их как можно быстрее. (По сути, проблема в том, что библиотека Java ImageIO очень медленно распаковывает эти файлы, и мы хотели бы заменить загрузчик собственным кодом через JNI, который улучшает это - в настоящее время это узкое место производительности.)

Здесь есть несколько примеров файлов - извинения всем, кто кулрофобен :

И здесь вы можете увидеть результаты попыток просмотра изображений в оттенках серого + альфа и RGB + альфа с помощью различного программного обеспечения Linux, которое, я считаю, использует libjpeg:

изображение в градациях серого с просмотром альфа-канала различными программами http://mythic -beasts.com / ~ mark / all-alpha-bridges.png

RGB-изображение с просмотром альфа-канала различными программами http://mythic -beasts.com / ~ mark / all-alpha-clowns.png

Похоже, что цветовое пространство просто неправильно интерпретируется в каждом случае. В jpeglib.h допускаются только следующие значения:

/* Known color spaces. */

typedef enum {
        JCS_UNKNOWN,            /* error/unspecified */
        JCS_GRAYSCALE,          /* monochrome */
        JCS_RGB,                /* red/green/blue */
        JCS_YCbCr,              /* Y/Cb/Cr (also known as YUV) */
        JCS_CMYK,               /* C/M/Y/K */
        JCS_YCCK                /* Y/Cb/Cr/K */
} J_COLOR_SPACE;

... что не выглядит многообещающе.

Если я загружаю эти изображения со слегка измененной версией example.c из libjpeg, значения cinfo.jpeg_color_space и cinfo.out_color_space для каждого изображения после прочтения заголовка следующие:

gray-normal.jpg: jpeg_color_space is JCS_GRAYSCALE, out_color_space is JCS_GRAYSCALE
gray-alpha.jpg: jpeg_color_space is JCS_CMYK, out_color_space is JCS_CMYK

rgb-normal.jpg: jpeg_color_space is JCS_YCbCr, out_color_space is JCS_RGB
rgb-alpha.jpg: jpeg_color_space is JCS_CMYK, out_color_space is JCS_CMYK

Итак, мои вопросы:

  • Может ли libjpeg использоваться для правильного чтения этих файлов?
  • Если нет, могу ли я использовать альтернативную библиотеку C, которая справится с ними?

Очевидно, что есть как минимум два других решения более общей проблемы:

  1. Изменить программное обеспечение для вывода обычных JPEG + файл PNG, представляющий альфа-канал
  2. Каким-то образом улучшить производительность Sun ImageIO

... но первое повлекло бы за собой множество изменений кода, и неясно, как поступить с последним. В любом случае, я думаю, что вопрос о том, как использовать libjpeg для загрузки таких файлов, вероятно, будет представлять более общий интерес.

Любые предложения приветствуются.

Ответы [ 3 ]

2 голосов
/ 06 июня 2011

Даже если вы сохраняете ваши изображения в виде 4-канальных изображений в формате JPEG, я не знаю стандартизированного способа определения формата цвета в файле JPEG.

Стандарт JFIF предполагает YCbCr.

1 голос
/ 02 июня 2011

Я попытался запустить libjpeg-turbo на цветных изображениях, которые имеют альфа-канал и которые были сохранены с ImageIO java как jpeg.

Вот как я скомпилировал libjpeg-turbo для linux 64-bit:

$ autoreconf -fiv
$ mkdir build
$ cd build
$ sh ../configure --with-java CPPFLAGS="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
$ make
$ cd ..
$ mkdir my-install
$ cd build
$ make install prefix=$PWD/../my-install libdir=$PWD/../my-install/lib64

Вот как я запускаю Фиджи с правильным путем к библиотеке и путем к классу, чтобы включить libjpeg-turbo:

$ cd Programming/fiji
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/../java/libjpeg-turbo/libjpeg-turbo/my-install/lib64
$ ./fiji -cp $PWD/../java/libjpeg-turbo/libjpeg-turbo/my-install/classes/turbojpeg.jar

Это небольшой jython-скрипт для чтения таких файлов jpeg + alpha:

######
path = "/home/albert/Desktop/t2/trakem2.1263462814399.1347985440.1111111/trakem2.mipmaps/0/17.07may04b_GridID02043_Insertion001_00013gr_00005sq_00014ex.tif.jpg"

from org.libjpegturbo.turbojpeg import TJDecompressor, TJ
from java.io import File, FileInputStream
from java.awt.image import BufferedImage
from jarray import zeros

f = File(path)
fis = FileInputStream(f)
b = zeros(fis.available(), 'b')
print len(b)
fis.read(b)
fis.close()

d = TJDecompressor(b)
print d.getWidth(), d.getHeight()
bi = d.decompress(d.getWidth(), d.getHeight(), BufferedImage.TYPE_INT_ARGB, 0)

ImagePlus("that", ColorProcessor(bi)).show()
####

Проблема: независимо от того, какой флаг я использую ('0' выше при вызове распаковки) из класса TJ (см. http://libjpeg -turbo.svn.sourceforge.net / viewvc / libjpeg-turbo /trunk/java/doc/org/libjpegturbo/turbojpeg/TJ.html), я не могу загрузить jpeg.

Вот сообщение об ошибке:

Started turbojpeg.py at Thu Jun 02 12:36:58 EDT 2011
Traceback (most recent call last):
  File "", line 15, in 
    at org.libjpegturbo.turbojpeg.TJDecompressor.decompressHeader(Native Method)
    at org.libjpegturbo.turbojpeg.TJDecompressor.setJPEGImage(TJDecompressor.java:89)
    at org.libjpegturbo.turbojpeg.TJDecompressor.(TJDecompressor.java:58)
    at sun.reflect.GeneratedConstructorAccessor10.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.python.core.PyReflectedConstructor.constructProxy(PyReflectedConstructor.java:210)

java.lang.Exception: java.lang.Exception: tjDecompressHeader2(): Could not determine subsampling type for JPEG image 

Таким образом, похоже, что либо libjpeg-turbo не может прочитать jpeg с альфа-каналом, сохраненным ImageIO, либо существует очень неочевидная настройка в вызове «распаковать», которую я не могу понять.

1 голос
/ 02 июня 2011

Вы уже пробовали libjpeg-turbo ? Предполагается, что он способен декодировать RGBA, и для него уже есть Java-оболочка.

...