用于检测 CMYK 图像的 JAI ImageIO 的纯 Java 替代品 [英] Pure Java alternative to JAI ImageIO for detecting CMYK images

查看:30
本文介绍了用于检测 CMYK 图像的 JAI ImageIO 的纯 Java 替代品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

first I'd like to explain the situation/requirements that lead to the question:

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

In our web application we can't support CMYK images (JPEG) since IE 8 and below can't display them. Thus we need to detect when someone wants to upload such an image and deny it.

不幸的是,Java 的 ImageIO 不会读取这些图像或无法让我获得检测到的色彩空间.从调试来看,JPEGImageReader 似乎在内部获得了颜色空间代码 11(这意味着 JCS_YCCK),但我无法安全地访问该信息.

Unfortunately, Java's ImageIO won't read those images or would not enable me to get the detected color space. From debugging it seems like JPEGImageReader internally gets the color space code 11 (which would mean JCS_YCCK) but I can't safely access that information.

当向阅读器查询图像类型时,我对 CMYK 一无所获,因此我可能假设 没有图像类型 = 不支持的图像.

When querying the reader for the image types I get nothing for CMYK, so I might assume no image types = unsupported image.

我使用成像工具将源 CMYK 图像转换为 RGB,以测试它是否可读(当收到不支持 CMYK"消息时,我尝试模拟管理员的步骤).但是,JPEGImageReader 不会读取该图像,因为它假定(在源代码中注释!)3 分量 RGB 颜色空间,但图像标题报告 4 个分量(可能是 RGBA 或ARGB) 并因此抛出 IllegalArgumentException.

I converted the source CMYK image to RGB using an imaging tool in order to test whether it would then be readable (I tried to simulate the admin's steps when getting the message "No CMYK supported"). However, JPEGImageReader would not read that image, since it assumes (comment in the source!)3-component RGB color space but the image header reports 4 components (maybe RGBA or ARGB) and thus an IllegalArgumentException is thrown.

因此,ImageIO 不是一个选项,因为我无法可靠地获得图像的色彩空间,而且我无法告诉管理员为什么一个原本不错的图像(它可以由浏览器显示)不会被接受,因为到一些内部错误.

Thus, ImageIO is not an option since I can't reliably get the color space of an image and I can't tell the admin why an otherwise fine image (it can be displayed by the browser) would not be accepted due to some internal error.

这让我尝试了 JAI ImageIO,它的 CLibJPEGImageReader 做得非常好,可以正确读取我所有的测试图像.

This led me to try JAI ImageIO whose CLibJPEGImageReader does an excellent job and correctly reads all my test images.

但是,由于我们将应用程序部署在可能托管其他应用程序的 JBoss 中,因此我们希望尽可能将它们隔离.AFAIK,我需要将 JAI ImageIO 安装到 JRE 或以其他方式使本机库可用才能使用它们,因此其他应用程序也可能访问它们,这可能会导致副作用(至少我们有进行大量测试以确保情况并非如此).

However, since we're deploying our application in a JBoss that might host other applications as well, we'd like to keep them as isolated as possible. AFAIK, I'd need to install JAI ImageIO to the JRE or otherwise make the native libs available in order to use them, and thus other applications might get access to them as well, which might cause side effects (at least we'd have to test a lot to ensure that's not the case).

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

That's the explanation for the question, and here it comes again: Is there any pure Java alternative to JAI ImageIO which reliably detects and possibly converts CMYK images?

提前致谢,

托马斯

推荐答案

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

I found a solution that is ok for our needs: Apache Commons Sanselan. This library reads JPEG headers quite fast and accurate (at least all my test images) as well as a number of other image formats.

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

The downside is that it won't read JPEG image data, but I can do that with the basic JRE tools.

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

Reading JPEG images for conversion is quite easy (the ones that ImageIO refuses to read, too):

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

然后,如果 Sanselan 告诉我图像实际上是 CMYK,我会获取源图像的​​光栅并自行转换:

Then if Sanselan tells me the image is actually CMYK, I get the source image's raster and convert myself:

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 转换状态有所不同,我只是尝试乘法以查看视觉结果.

This give quite good results in the RGB images not being too bright or dark. However, I'm not sure why multiplying with k prevents the brightening. The JPEG is actually decoded in native code and the CMYK->RGB conversion I got states something different, I just tried the multiply to see the visual result.

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

If anybody could shed some light on this, I'd be grateful.

这篇关于用于检测 CMYK 图像的 JAI ImageIO 的纯 Java 替代品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆