我能用libjpeg读取带有alpha通道的JPEG吗?

11

关于JPEG带alpha通道是否有效似乎存在一些争议。我一直认为的答案是在JPEG FAQ中给出的,基本上是“不行”。(这在Stack Overflow的另一个问题中也有强调。)

然而,Sun的ImageIO库中的Java JPEGImageWriter可以轻松地写入和读取带有alpha通道的灰度和RGB图像,尽管到目前为止我尝试过的Linux应用程序中几乎没有一个能够正确加载这样的JPEG。这曾被报告为一个错误,但Sun的回应是这些是有效的文件

这不是Image I/O的错误,而是提交者提到的其他应用程序的缺陷。IIO JPEGImageWriter能够写入包含alpha通道的颜色模型的图像(在IJG本机源代码中称为“NIFTY”颜色空间,例如RGBA、YCbCrA等),但许多应用程序不知道这些颜色空间。因此,即使这些由IIO JPEG writer编写的图像符合JPEG规范(该规范对各种颜色空间可能性视而不见),一些应用程序可能无法识别包含alpha通道的颜色空间,并可能抛出错误或呈现损坏的图像,如提交者所描述的那样。 希望与这些不支持alpha通道的应用程序保持兼容性的开发人员应编写不包含alpha通道的图像(例如TYPE_INT_RGB)。想要在JPEG格式中写入/读取包含alpha通道的图像的开发人员可以使用Image I/O API实现,但需要注意许多本地应用程序并不完全符合YCbCrA和RGBA格式。 有关更多信息,请参阅Image 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 的人表示歉意:

在这里,您可以看到使用各种Linux软件查看带有alpha通道的灰度+alpha和RGB+alpha图像的结果,我相信这些软件使用了libjpeg

使用各种程序查看带有alpha通道的灰度图像 http://mythic-beasts.com/~mark/all-alpha-bridges.png

使用各种程序查看带有alpha通道的RGB图像
(来源:来自mythic-beasts.com的马克)

因此,在每种情况下,颜色空间似乎都被错误解释了。 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.clibjpeg加载这些图片,读取头文件后每个图像的cinfo.jpeg_color_spacecinfo.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和表示alpha通道的PNG文件
  2. 以某种方式提高Sun的ImageIO性能

...但第一个方法将涉及大量代码更改,而后者如何着手也不清楚。无论如何,我认为如何使用libjpeg加载这样的文件的问题很可能是更普遍的兴趣。

任何建议将不胜感激。

3个回答

3
即使您将图像存储为4通道jpeg图像,我不知道如何在jpeg文件中指定颜色格式的标准化方法。JFIF标准假定为YCbCr。

1

我尝试在具有 alpha 通道并使用 Java 的 ImageIO 保存为 JPEG 格式的彩色图像上运行 libjpeg-turbo。

以下是我为 Linux 64 位编译 libjpeg-turbo 的方法:

$ 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

这是我如何使用正确的库路径和类路径运行Fiji,以包括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。

以下是错误消息:
2011年6月2日,星期四,开始运行turbojpeg.py 最近的调用记录: 在org.libjpegturbo.turbojpeg.TJDecompressor.decompressHeader(本机方法)处, 在org.libjpegturbo.turbojpeg.TJDecompressor.setJPEGImage(TJDecompressor.java:89)处, 在org.libjpegturbo.turbojpeg.TJDecompressor.(TJDecompressor.java:58)处, 在sun.reflect.GeneratedConstructorAccessor10.newInstance(未知来源)处, 在sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)处, 在java.lang.reflect.Constructor.newInstance(Constructor.java:513)处, 在org.python.core.PyReflectedConstructor.constructProxy(PyReflectedConstructor.java:210)处。
java.lang.Exception:java.lang.Exception:tjDecompressHeader2():无法确定JPEG图像的子采样类型
因此,似乎libjpeg-turbo无法读取由ImageIO保存的带有alpha的jpeg,或者在“解压缩”调用中存在非常不明显的设置,我无法理解。

1

你已经尝试过libjpeg-turbo了吗?它应该能够解码RGBA,并且已经有一个Java包装器可用。


不,我不知道!谢谢你的建议。 - Mark Longair
1
很遗憾,我无法让libjpeg-turbo正确解码这些图像,但我将接受它作为最有帮助的答案。 - Mark Longair
刚刚阅读了libjpegturbo的文档,它说会删除第四个通道。所以如果我理解正确的话,就没有alpha通道了。 - Chameleon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接