问题描述
我有一个使用 ImageIO 将字节数组转换为 BufferedImage 的代码.
I have a code that turns a byte array into BufferedImage using ImageIO.
public void readImage(byte[] imageBytes) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
// do something with bufferedImage
}
但我发现对于某些 jpeg 图像,它每次都会抛出 CMMException.
But I found that for certain jpeg images, it throws a CMMException, every time.
这是堆栈跟踪:
java.awt.color.CMMException: Cannot get color transform
at sun.java2d.cmm.lcms.LCMS.createNativeTransform(Native Method)
at sun.java2d.cmm.lcms.LCMSTransform.<init>(LCMSTransform.java:103)
at sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:75)
at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:552)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1251)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1219)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1022)
at javax.imageio.ImageIO.read(ImageIO.java:1438)
at javax.imageio.ImageIO.read(ImageIO.java:1342)
这是导致问题的照片
我在 Google 上搜索了一个解决方案,并找到了一个承认该问题并建议在 ImageIO 失败的情况下使用 JAI 的帖子.但我有疑问,因为帖子是 4 年前的,我似乎找不到关于 JAI 的太多信息,这让我相信这不是理想的解决方案.有没有其他方法可以在没有 ImageIO 或 JAI 的情况下将字节数组转换为缓冲图像?如果 JAI 今天仍然是一个可靠的解决方案,有人可以告诉我如何使用 JAI 做到这一点吗?
I searched on Google for a solution, and found a post acknowledging the problem and recommending to use JAI for cases where ImageIO fails. But I'm having doubts, as the post was from 4 years ago, and I can't seem to find much information about JAI, leading me to believe that that's not the ideal solution. Is there any other way to convert byte array into buffered image without ImageIO or JAI? And if JAI is still a solid solution today, could someone show me how to do that using JAI?
提前致谢!
推荐答案
首先可以使用我的 TwelveMonkeys JPEG 插件用于 ImageIO,它将阅读此 JPEG.无需更改您的代码.据我所知,问题在于它包含一个 Corbis RGB ICC 颜色配置文件,使用过时或损坏的 ICC 配置文件格式.我的阅读器会在运行时修补 ICC 配置文件,然后读取图像就好了.
First of all, you can use my TwelveMonkeys JPEG plugin for ImageIO, it will read this JPEG. No need to change your code. From what I remember, the issue was that it contains a Corbis RGB ICC color profile, using an outdated or broken ICC profile format. My reader will patch the ICC profile at runtime, and read the image just fine.
此外,堆栈跟踪中的 LCMS 引用表明您使用的是 OpenJDK 或 Java 8.至少对于 Java 8,有一个开关-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
重新启用 Kodak CMS(在 Java 8 之前的所有 Sun/Oracle JRE 中使用),在 LittleCMS 被选为默认设置之后来自 Java 8.这些颜色管理系统处理 ICC 配置文件的方式略有不同,因此在某些情况下设置此开关可能会有所帮助.
Further, the LCMS references in the stack trace indicates you are either on OpenJDK or, Java 8. For Java 8 at least, there is a switch-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
to re-enable the Kodak CMS (used in all Sun/Oracle JREs pre Java 8), after LittleCMS was chosen as the default from Java 8. There are minor differences in how these color management systems handle ICC profiles, so setting this switch might help in certain cases.
更新:我只是尝试读取图像,Java 版本 1.7.0_60 可以读取图像,但是颜色略微偏离(它变成紫色,就像在 Chrome 中一样),因为忽略了 ICC 配置文件.这对你来说可能已经足够了.如果没有,请使用 TwelveMonkeys JPEG 插件.:-)
Update: I just tried to read the image, and Java version 1.7.0_60 could read the image, however the colors are slightly off (it gets a purple tint, like in Chrome), because the ICC profile is ignored. This might be good enough for you. If not, use the TwelveMonkeys JPEG plugin. :-)
这篇关于将字节数组读入缓冲图像而无需 ImageIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!