我可以使用 libjpeg 读取带有 Alpha 通道的 JPEG 吗?

发布于 2024-11-13 06:40:51 字数 3664 浏览 5 评论 0原文

关于带有 Alpha 通道的 JPEG 是否有效似乎存在一些争论。我一直认为正确的答案是 JPEG 中的答案FAQ,本质上是“否”。 (Stack Overflow 上的另一个问题重申了这一点。)

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

这不是图像 I/O 错误,而是其他应用程序的缺陷 提交者提到。 IIO JPEGImageWriter 能够使用以下方式写入图像 包含 alpha 通道的颜色模型(在 IJG 原生中引用) 源代码中称为“NIFTY”颜色空间,例如 RGBA、YCbCrA 等),但许多应用程序并不知道这些颜色空间。所以即使这些图像 由 IIO JPEG writer 编写的图像符合 JPEG 规范( 对各种色彩空间的可能性视而不见),某些应用程序可能不会 识别包含 Alpha 通道的颜色空间,并可能会抛出 错误或渲染损坏的图像,如提交者所述。

希望与其他 alpha 版本保持兼容的开发人员 应用程序应该编写不包含 Alpha 通道的图像(例如 类型_INT_RGB)。想要写入/读取图像功能的开发人员 包含 JPEG 格式的 Alpha 通道可以使用图像 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的人道歉:

在这里您可以看到尝试查看我相信使用 libjpeg 的各种 Linux 软件的灰度+alpha 和 RGB+alpha 图像:

带有各种程序的 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;

...这看起来不太有希望。

如果我使用 libjpeg 中稍加修改的 example.c 版本加载这些图像,则 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 加载此类文件的问题可能是更普遍的兴趣之一。

任何建议将不胜感激。

There seems to be some debate about whether JPEGs with alpha channels are valid or not. The answer I had always understood to be correct is that in the JPEG FAQ, which is essentially "No". (This is reiterated in another question on Stack Overflow.)

However, Java's JPEGImageWriter in Sun's ImageIO library will happily write and read grayscale and RGB images with an alpha channel, even though there are virtually no applications on Linux I've tried so far that will load such JPEGs correctly. This has been reported in the past as a bug, but Sun's response is that these are valid files:

This is not an Image I/O bug, but rather a deficiency in the other applications
the submitter mentions. The IIO JPEGImageWriter is able to write images with
a color model that contains an alpha channel (referred to in the IJG native
source code as the "NIFTY" color spaces, such as RGBA, YCbCrA, etc.), but many applications are not aware of these color spaces. So even though these images
written by the IIO JPEG writer are compliant with the JPEG specification (which
is blind to the various color space possiblities), some applications may not
recognize color spaces that contain an alpha channel and may throw an
error or render a corrupted image, as the submitter describes.

Developers wishing to maintain compatibility with these other alpha-unaware
applications should write images that do not contain an alpha channel (such as
TYPE_INT_RGB). Developers who want the capability of writing/reading an image
containing an alpha channel in the JPEG format can do so using the Image I/O
API, but need to be aware that many native applications out there are not quite
compliant with the YCbCrA and RGBA formats.

For more information, see the Image I/O JPEG Metadata Format Specification and Usage Notes:
http://java.sun.com/j2se/1.4.1/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html

Closing as "not a bug".
xxxxx@xxxxx 2003-03-24

I'm working with a Java application that creates files like these, and want to write some C code that will load these as fast as possible. (Essentially the problem is that the Java ImageIO library is remarkably slow at decompressing these files, and we would like to replace the loader with native code via JNI that improves this - it's a performance bottleneck at the moment.)

There are some example files here - apologies to anyone who's coulrophobic:

And here you can see the results of trying to view the grayscale+alpha and RGB+alpha images with various bit of Linux software that I believe use libjpeg:

grayscale image with alpha channel view with various programs http://mythic-beasts.com/~mark/all-alpha-bridges.png

RGB image with alpha channel view with various programs
(source: mark at mythic-beasts.com)

So it looks as if the color space is just being misinterpreted in each case. The only allowed values in jpeglib.h are:

/* 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;

... which doesn't look promising.

If I load these images with a slightly modified version of example.c from libjpeg, the values of cinfo.jpeg_color_space and cinfo.out_color_space for each image after reading the header are as follows:

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

So, my questions are:

  • Can libjpeg be used to correctly read these files?
  • If not, is there an alternative C library I can use which will cope with them?

Obviously there are at least two other solutions to the more general problem:

  1. Change the software to output normal JPEGs + a PNG file representing the alpha channel
  2. Somehow improve the performance of Sun's ImageIO

... but the first would involve a lot of code changes, and it's not clear how to go about the latter. In any case, I think that the question of how to use libjpeg to load such files is likely to be one of more general interest.

Any suggestions would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

著墨染雨君画夕 2024-11-20 06:40:51

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

JFIF 标准假定 YCbCr。

Even if you store your images as 4 channel jpeg images, there's no standardized way I know of how to specify the color format in the jpeg file.

The JFIF standard assumes YCbCr.

毅然前行 2024-11-20 06:40:51

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

Have you already tried libjpeg-turbo? It is supposed to be able to decode RGBA and there is already a Java wrapper for it.

雅心素梦 2024-11-20 06:40:51

我尝试在具有 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

这是一个用于读取此类 jpeg+alpha 文件的小 jython 脚本:

######
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()
####

问题:无论我使用 TJ 类中的哪个标志(上面调用解压缩时的“0”)(请参阅 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 无法读取由 ImageIO 保存的带有 alpha 的 jpeg,或者在调用“解压缩”时有一个非常不明显的设置,我无法理解。

I have tried running libjpeg-turbo on color images that have an alpha channel and which have been saved with java's ImageIO as jpeg.

This is how I compiled libjpeg-turbo for 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

This is how I run Fiji with the correct library path and classpath, to include 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

This is a small jython script to read such jpeg+alpha files:

######
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()
####

The problem: no matter what flag I use (the '0' above in the call to decompress) from the TJ class (see http://libjpeg-turbo.svn.sourceforge.net/viewvc/libjpeg-turbo/trunk/java/doc/org/libjpegturbo/turbojpeg/TJ.html), I cannot get the jpeg to load.

Here's the error message:

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 

So it appears that either libjpeg-turbo cannot read jpeg with alpha as saved by ImageIO, or there is a very non-obvious setting in the call to "decompress" that I am unable to grasp.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文