ImageIO.read红色调问题

什么是红色调问题

在写一个压缩图像的工具类的时候,发现该问题。原图如下,大小为3.8M,格式为png
在这里插入图片描述
压缩之后,变成以下这样,大小为1.4M,格式为jpeg
在这里插入图片描述
搜了下网上有的说是:有损压缩算法会牺牲图像的一些细节和信息以减小文件大小,从而导致图像质量的损失。虽说是有损,但这是不是损的太厉害了,色调变化也太大了。真的是这样吗?

排查

在翻了好多的资料以后,终于搜到了一些靠谱的词:红色调。这不就是我压缩后图像的色调吗?顺着一搜,找到这篇:
Toolkit.getDefaultToolkit().createImage() vs ImageIO.read()

大概理解了问题的所在,再深入扒一下,得到了以下内容:只影响一些特定类型的JPEG图像,它们有一种特殊的子采样方式,并且没有JFIF标记。当ImageIO读取这些图像时,它会错误地将YCbCr数据解释为RGB数据,从而导致颜色失真

那什么是YCbCr数据呢?

YCbCr

YCbCr数据是一种用来表示颜色的模型,它使用一个亮度分量(Y)和两个色差分量(Cb和Cr)来定义颜色数据。它常用于数字图像和视频场景中。YCbCr这个术语经常和YUV混用,尽管它们在技术上是不同的。在YCbCr中,Y表示颜色的明亮度和浓度,而Cb和Cr则分别表示颜色的蓝色浓度偏移量和红色浓度偏移量。YCbCr数据通常使用平面的内存布局来存储,这意味着每个颜色分量都单独存储在自己的连续平面中,总共有三个平面。YCbCr数据可以通过数学变换从RGB颜色空间转换而来,也可以反过来转换回RGB。

也就是说ImageIO.read()方法将YCbCr数据直接解释为了RGB数据才导致上面的结果

解决

知道了问题的原因,那么我直接换个能正确读取YCbCr数据的方法来不就好了。

将以下代码,其中inputImage为图像的File对象

BufferedImage image = ImageIO.read(inputImage);

替换为:

        Image image1 = Toolkit.getDefaultToolkit().getImage(inputImage.getAbsolutePath());
        // 等待图像加载完成
        MediaTracker mediaTracker = new MediaTracker(new Component() {});
        mediaTracker.addImage(image1, 0);
        try {
            mediaTracker.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //转为BufferdImage对象
        BufferedImage image = toBufferedImage(image1);

toBufferedImage

public static BufferedImage toBufferedImage(Image image) {
		//设置一个同宽高的基本图像
        BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
        //空图像的画布
        Graphics2D g = bimage.createGraphics();
        //绘制图像
        g.drawImage(image, 0, 0, null);
        //释放资源
        g.dispose();
        return bimage;
    }

修改后得到的压缩图片文件如下,大小为1.4M
在这里插入图片描述
至此大功告成。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值