JPEG 图像颜色错误
我有一种读取图像、转换图像(大小、格式)并将其写回的方法。这一直很有效,但现在我遇到了一些 JPEG 图像(来自新闻机构),它们显然包含一些元数据 (IPTC)。转换这些图像时,颜色全部错误。我的第一个猜测是,这些是 CMYK 图像,但事实并非如此。
问题一定来自于阅读,因为无论我将图像转换为较小的JPEG还是PNG并不重要,它看起来总是一样的。
首先,我使用ImageIO.read()
来读取图像。我现在通过 ImageIO.getImageReadersByMIMEType()
获取实际的 ImageReader
,并尝试通过设置 ignoreMetadata
参数来告诉读者忽略元数据code>ImageReader#setInput(Object input, booleaneekForwardOnly,booleanignoreMetadata) 但没有成功。
然后我创建了一个没有元数据的图像版本(使用 Fireworks)。该图像已正确转换。
我能发现的唯一区别是,对于非工作图像,读取器变量 colorSpaceCode
的值为 2,而对于工作图像,该值为3。还有一个 outColorSpaceCode
,这两个图像的值都是 2。
作为读者的源注释< /a> 仅表示由 setImageData 本机代码回调设置。修改后的 IJG+NIFTY 色彩空间代码 我现在真的陷入困境了。因此,任何帮助将不胜感激。
您可以前往此处并点击下载来获取原始图片 (~3 MB)。下面的左图显示了我从原始图像中得到的内容,右图显示了它应该是什么样子。
I have a method that reads images, converts them (size, format) and writes them back. This always worked very well, but now I've come across some JPEG images (from a Press Agency) that obviously contain some meta-data (IPTC). When converting those images, the colors are all wrong. My first guess was, that those are CMYK images but they are not.
The problem must come from the reading, because it doesn't matter whether I convert the image to a smaller JPEG or a PNG, it always looks the same.
At first, I used ImageIO.read()
to read the image. I now get the actual ImageReader
via ImageIO.getImageReadersByMIMEType()
and tried to tell the reader to ignore meta data by setting the ignoreMetadata
parameter of ImageReader#setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata)
but had no success.
Then I created a version of the image without the metadata (using Fireworks). That image is converted correctly.
The only difference I could find out, is, that with the not-working image the value of the reader's variable colorSpaceCode
is 2, whilest with the working image, the value is 3. There's also an outColorSpaceCode
which is 2 for both images.
As the source comment of the reader only says Set by setImageData native code callback. A modified IJG+NIFTY colorspace code I'm really stuck now. So any help would be much appreciated.
You can get original image (~3 MB) by going here and clicking download. The left image below shows what I get from the original image, the right shows what it should look like.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我现在找到了一个可行的解决方案,至少如果我生成的图像也是 JPEG:
首先,我读取图像(来自字节数组 imageData),最重要的是,我还读取元数据。
现在我会做一些转换(即缩小尺寸)...最后我会将结果作为 JPEG 图像写回。这里最重要的是将我们从原始图像获得的元数据传递给新的
IIOImage
。不幸的是,如果我写一个 PNG 图像,我仍然会得到错误的颜色(即使传递元数据),但我可以忍受。
I found a solution now, that works, at least if my resulting image is also a JPEG:
First I read the image (from byte array imageData), and most important, I also read the metadata.
Now i'd do some converting (i.e. shrink in size) ... and at last I'd write the result back as a JPEG image. Here it is most important to pass the metadata we got from the original image to the new
IIOImage
.Unfortunately, if I'd write a PNG image, I still get the wrong colors (even if passing the metadata), but I can live with that.
我遇到了类似的问题。我不得不使用:
而不是
I had a similar problem.I had to use:
instead of
我遇到了类似的问题,返回的 BufferedImage 是基于是否存在透明像素的再现,对于大多数 png/gif 类型的文件来说,这将设置为 true。但当转换为 jpeg 时,该标志应设置为 false。您可能需要编写一个方法来正确处理转换。即:
否则“marunish”泛音将成为保存的结果。 :)
I had similar problems, the
BufferedImage
returned is a rendition based if there is transparent pixel, which will be set true for most png/gif type of files. But when converting to jpeg this flag should be set to false. You need possibly to write a method, where the conversion is properly handled. i.e.:Otherwise that "marunish" overtone becomes the saved result. :)
我遇到了这个问题,实际上我找到了一个第三方库来为我处理这个问题。 https://github.com/haraldk/TwelveMonkeys
从字面上看,我要做的就是将其包含在我的 Maven 中依赖项和以奇怪颜色出现的 jpeg 开始正常读取。我什至不必更改一行代码。
I was running into this issue, and I actually found a third party library that handled this for me. https://github.com/haraldk/TwelveMonkeys
Literally all I had to do was include this in my maven dependencies and the jpegs that were coming out in weird colors started getting read in normally. I didn't even have to change a line of code.
当我尝试将图像从字节数组转换为 Base64 时,我遇到了类似的问题。该问题似乎是由带有 Alpha 通道的图像引起的。保存带有 Alpha 通道的图像时,Alpha 通道也会被保存,并且一些用于读取图像的外部程序将 4 个通道解释为 CMYK。
找到了一个简单的解决方法,通过删除 BufferedImage 的 Alpha 通道。这可能很愚蠢,但它确实对我有用。
I had a similar problem when trying to convert an image from a byte array to Base64. It appears the problem is caused by images with an alpha channel. When saving an image with an alpha channel, the alpha channel is saved too and some external programs that are used to read the image interpret the 4 channels as CMYK.
Found a simple workaround, by removing the alpha channel of the BufferedImage. This may be stupid but it sure worked for me.
请注意,问题可能发生在各个阶段:
我最近遇到的情况是上传 Greenshot 创建的
png
屏幕截图时,使用ImageIO
读取,缩放然后用ImageIO
asjpeg
(典型的缩略图处理)。我的书写方面的解决方案:删除 alpha 通道以避免浏览器将图像解释为 YMCK):
Note that problems can happen at various stages:
ImageIO.write()
)My latest encounter with this was when uploading
png
screenshots created by Greenshot, reading withImageIO
, scaling and then writing withImageIO
asjpeg
(your typical thumbnail process).My solution for the writing side: remove alpha channel to avoid browsers interpreting the image as YMCK):
这是一种将“坏”图像转换为好图像的算法,但是,我还没有找到任何方法来自动检测图像是否会渲染得很差,所以它仍然没有用。
如果有人找到一种方法来检测图像是否会渲染不良(除了目视),请告诉我们。 (比如,我从哪里获得这个所谓的
colorSpaceCode
值?!)Here's an algorithm to transform the 'bad' image into a good one, however, I have not found any way of automatically detecting if an image will be rendered badly, so it is still useless.
If anyone finds a way to detect if an image will be rendered bad (other than eyeballing), please tell us. (like, where do I get this so-called
colorSpaceCode
value?!)这里看起来不错:
Seems fine here:
当原始 jpg 以 CMYK 颜色保存时会出现此问题。在 fe Paint 中将其重新着色为 RGB 彩色图像
The problem occurs when the original jpg was saved in CMYK color. Recolor it as an RGB color image in f.e. Paint