Можно ли использовать libjpeg для чтения JPEG с альфа-каналом?

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

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

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

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

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

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

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

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

И здесь вы можете увидеть результаты попыток просмотра изображений в оттенках серого + альфа и 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, которую я могу использовать, которая будет с ними справляться?

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

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

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

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

Ответ 1

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

Ответ 2

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

В стандарте JFIF предполагается YCbCr.

Ответ 3

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

Вот как я скомпилировал libjpeg-turbo для 64-разрядного Linux:

$ 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

Вот как я запускаю Фиджи с правильным пути библиотеки и pathpath, чтобы включить 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 script для чтения таких файлов 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, или есть очень неочевидная настройка в вызове "распаковать", который я не могу понять.