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

Tho*_*mas 13 java cmyk jai javax.imageio

首先,我想解释导致问题的情况/要求:

在我们的Web应用程序中,我们无法支持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中,因此我们希望尽可能保持它们的隔离.据我所知,我需要JAI ImageIO的安装到JRE或以其他方式使本机库提供,以使用它们,因此,其他应用程序可能访问到它们为好,这可能会导致副作用(至少我们不得不测试很多,以确保不是这种情况).

这就是问题的解释,这里再次出现: JAI ImageIO是否有任何纯Java替代品可以可靠地检测并可能转换CMYK图像?

提前致谢,

托马斯

Tho*_*mas 11

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

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

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

JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream( new File(pFilename) ) );
BufferedImage sourceImg = decoder.decodeAsBufferedImage();
Run Code Online (Sandbox Code Playgroud)

然后如果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;
}
Run Code Online (Sandbox Code Playgroud)

这在RGB图像不太亮或太暗的情况下给出了相当好的结果.但是,我不确定为什么乘以k防止增亮.JPEG实际上是用本机代码解码的,CMYK-> RGB转换得到了不同的状态,我只是尝试乘法来看到视觉效果.

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


Cod*_*odo 5

我已经发布了一个纯 Java解决方案,用于读取各种 JPEG 图像并将它们转换为 RGB。

它建立在以下事实之上:

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