用于检测CMYK图像的JAI ImageIO的纯Java替代品

时间:2011-07-26 11:38:53

标签: java javax.imageio jai 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图像?

提前致谢,

托马斯

4 个答案:

答案 0 :(得分:10)

我找到了一个可以满足我们需求的解决方案:Apache Commons Sanselan。这个库可以非常快速准确地读取JPEG标题(至少是我的所有测试图像)以及许多其他图像格式。

缺点是它不会读取JPEG图像数据,但我可以使用基本的JRE工具。

读取JPEG图像进行转换非常简单(ImageIO也拒绝阅读):

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

然后如果Sanselan告诉我图像实际上是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转换我得到了不同的状态,我只是尝试乘法来看到视觉效果。

如果有人能对此有所了解,我将不胜感激。

答案 1 :(得分:4)

我发布了一个纯Java solution,用于读取各种JPEG图像并将其转换为RGB。

它基于以下事实:

  • 虽然ImageIO无法使用CMYK作为缓冲图像读取JPEG图像,但它可以读取原始像素数据(光栅)。
  • Sanselan(或现在称为Apache Commons Imaging)可用于阅读CMYK图像的详细信息。
  • 存在具有反转CMYK值的图像(旧的Photoshop错误)。
  • 有YCCK而不是CMYK的图像(可以轻松转换)。

答案 2 :(得分:2)

  

在我们的网络应用程序中,我们无法支持CMYK图像(JPEG)   IE 8及以下版本无法显示它们。因此我们需要检测何时有人   想要上传这样的图片并拒绝它。

我不同意你的“因此我们需要检测何时有人想要上传这样的图片并拒绝”。一个更加用户友好的政策是将其转换为CMYK之外的其他东西。

你的帖子的其余部分有点令人困惑,因为看到你要求检测和转换,这是两个不同的事情。再一次,我认为转换图像更加用户友好。

无需用粗体btw书写:

  

是否有可靠的JAI ImageIO的纯Java替代品   检测并可能转换CMYK图像?

纯Java我不知道,但ImageMagick可以很好地将CMYK图像转换为RGB图像。从Java调用服务器端的 ImageMagick 并不复杂。我曾经通过调用外部进程手动完成它,但现在有包含 JMagick im4java 的包装器。

答案 3 :(得分:2)

请注意另一篇文章,因为Java 7不允许在没有import com.sun.image.codec.jpeg.*中所示的特殊参数的情况下直接使用Sun的实现。