16

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

在我们的 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 中,该 JBoss 也可能托管其他应用程序,因此我们希望使它们尽可能地隔离。AFAIK,我需要将 JAI ImageIO 安装到 JRE 或以其他方式使本机库可用才能使用它们,因此其他应用程序也可能访问它们,这可能会导致副作用(至少我们会有进行大量测试以确保不是这种情况)。

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

提前致谢,

托马斯

4

4 回答 4

14

我找到了一个可以满足我们需求的解决方案: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 转换我得到的状态有所不同,我只是尝试了乘法来查看视觉结果。

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

于 2011-08-01T16:20:23.500 回答
5

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

它建立在以下事实之上:

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

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

于 2014-01-10T12:54:24.587 回答
1

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

我不同意您的“因此我们需要检测何时有人想要上传这样的图像并拒绝它”。一个更加用户友好的策略是将其转换为 CMYK 以外的其他内容。

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

不需要用粗体写:

是否有任何纯 Java 替代 JAI ImageIO 可以可靠地检测并可能转换 CMYK 图像?

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

于 2011-07-26T12:38:50.577 回答