2009-08-13 71 views
10

当我读取某些JPG文件时,颜色会变平。下面是一个简单的例子,它读取一个jpg文件,并将相同的图像写入另一个文件。为什么Java ImageIO会使JPEG颜色变平整

import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 

public class JPegReadTest { 
    public static void main(String[] args) { 
     if (args.length == 2) { 
      try { 
       BufferedImage src = ImageIO.read(new File(args[0])); 
       ImageIO.write(src, "jpg", new File(args[1])); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      System.err.println("Usage: java JPegReadTest src dest"); 
     } 
    } 
} 

如果你尝试这个具有例如http://www.flickr.com/photos/visualpanic/233508614/sizes/l/,目标图像的颜色从源文件不同。这是为什么?如何解决它?

也尝试将图像保存为PNG,但颜色也是平淡(因此假设颜色信息不正确读取)。

+0

你有没有弄清楚如何保存颜色配置文件?我面临同样的问题 – 2011-03-16 01:30:05

回答

10

这可能有几个原因。

  1. JPEG颜色数据通常存储为YCrCb而不是RGB,但转换应该大部分不明显。
  2. JPEG通常有一个嵌入的颜色配置文件,但许多应用程序不理解这一点,并简单地忽略它(在这种情况下,您的输出文件可能会丢失颜色配置文件)。
  3. Java对它进行修改后,Gamma值可能会重置或丢失。

我没有真正尝试你的例子......你能请在文件之前和之后发布吗?如果没有真正能够检查结果文件,很难判断这些额外的数据是否存在。

编辑:是的,很明显,您的原始图像和转换后的图像具有不同的颜色配置文件。 Java删除了原始的颜色配置文件,而是使用了通用sRGB。他们在Windows上使用Firefox和各种程序看起来与我们一样,因为这些程序在渲染器时不使用颜色配置文件。但是,在你的Mac上,Mac实际上支持这些颜色配置文件(提示有关Mac的图形辩论等),因此它们渲染的方式不同。我没有Mac,但我怀疑如果你在任何平台上用Photoshop打开文件,你都会看到不同之处。

+0

好的,这里是前后文件。 http://terokinnunen.jalbum.net/Colortest/orig.jpg http://terokinnunen.jalbum.net/Colortest/converted-jpg.jpg 还试图保存为PNG,仍然平淡 的http:// terokinnunen .jalbum.net/Colortest/converted-png.png – ketorin 2009-08-13 13:54:10

+0

有趣的是:对于我来说(Ubuntu 9.04,Firefox 3.5/Gimp)原始和转换的外观几乎相同(modulu JPEG文物)。我可以用GIMP找到的唯一区别是原始文件指定“sRGB IEC61966-2.1”作为色彩空间,而转换文件具有“sRGB内置”。 – 2009-08-13 14:11:57

+0

他们呢?确实很有趣。对于我(Mac和Safari或Firefox),转换后的颜色明显不同。我也检查了Windows,并且令我惊讶的是他们看起来也差不多,只是略有差别。 – ketorin 2009-08-13 14:28:19

0

jpeg是一种有损格式。当读入时,java将其存储为原始格式,非常像BMP。然后它又被写出来导致数据丢失。而且,像使用GIMP这样的东西时,对质量的控制也很少。

也许看看使用其他API如Image Magick可以让您更好地控制质量。

+2

无关紧要。 OP指出了一个重要的色彩问题,而不仅仅是重新压缩。 – erjiang 2009-08-13 15:09:58

0

JPEGlossy格式。

这意味着,如果你打开一个文件并再次保存它,除非你采取非常具体的步骤,不要失去任何你会失去一些信息(在这种情况下,可能的操作是非常有限的)。

此外ImageIO.write()可能会使用一些默认的质量设置来保存JPEG文件,这可能会低于原始文件,这会导致额外的质量损失。

尝试保存到一个PNG文件,你会看到它的外观一样的来源。

+0

我尝试保存到PNG,但它也看起来平淡无奇,与jpg保存的图像相同。我有一种预感,即颜色甚至没有被正确读取。 – ketorin 2009-08-13 13:39:07

+0

在这种情况下,问题可能是某些颜色配置文件存储在Java不能读取/解释的图像中。 – 2009-08-13 13:48:56

2

也许你的源图像已与色域比sRGB宽的指定颜色配置文件(如Adobe RGB),和您的加载/保存周期不保留色彩空间信息?没有颜色配置文件,您的查看器将采用sRGB,并且压缩的色域会使所有内容看起来“无用”。如果你有exiftool,

exiftool -ProfileDescription filename.jpg 

是一个快速的方法来验证您的源和输出图像的颜色配置文件。

+0

是的,这可能是问题,配置文件确实从输出文件中丢失。这个线程看起来很有前景:http://forums.java.net/jive/thread.jspa?threadID=60631&tstart=0,接下来看看它。 – ketorin 2009-08-13 14:52:32

+0

哎呀,那是错误的线程:http://forums.java.net/jive/message.jspa?messageID=205964 – ketorin 2009-08-13 14:53:39

0

这里是源代码的链接,该ImageIO的界面上展开 - 写入图像时,你可以改变的质量和压缩参数.... http://www.universalwebservices.net/web-programming-resources/java/adjust-jpeg-image-compression-quality-when-saving-images-in-java

+0

这是模糊的。你有没有用这个问题的图片来试试它?基本上你要告诉OP *再次检查文档*。接受的答案表明,这个答案不能解决OP的问题。 – andr 2013-01-18 00:55:28

相关问题