为什么网络上一些表情包在反复传播之后会变绿?“电子包浆”到底是怎么形成的?

大家好,我是程序员牛肉。

今天在和朋友聊天的时候,他发了一张很古老的表情包,整张图片呈现很明显的发绿状态。

这张图片直接将我的思绪拉回到七八年前,当时我还经常在QQ群里和别人斗图。大家发一些很经典的表情包的时候,这些图片就会呈现明显的发绿状态,当时的大家戏称这玩意是"电子包浆"。

你们有这种充满"电子包浆"的图片嘛?可以发在评论区看一看。那大家有没有想过这些图片为什么会发绿呢?

我们首先要明确一点:图片并不是因为反复传播而变绿的,而是因为在传播的过程中,各个软件都会对图片进行压缩来节省网络带宽。在反复压缩的过程中,图片就会出现这种明显的"电子包浆"感。

问题的根源出在安卓自己的核心代码上,它对外提供了一个压缩图片的接口。而这个接口使用的是Google的图像库Skia来提供服务。

github.com/google/skia

对应的代码仓库

Google在Skip中采用了libjpeg - turbo来完成实际的压缩工作。而在进行压缩工作时,libjpeg - turbo 会先将图像从常见的 RGB 色彩空间转换为 YUV 色彩空间,这是整个压缩流程中的一个基础环节,为后续的离散余弦变换(DCT)、量化等压缩操作做准备。

libjpeg - turbo是一个对 JPEG 图像编码和解码进行加速的库,是对传统 JPEG 库的优化和改进版本,具有更高的压缩和解压缩速度,同时保持了良好的图像质量。Skia 在进行 JPEG 图像压缩时,会调用 libjpeg - turbo 来完成实际的压缩工作,借助 libjpeg - turbo 的高效算法和优化实现,提升 JPEG 压缩的性能和效果。

问题就出在RGB转YUV色彩空间的过程中,采用了降低精度来提高转换速度。而在这一过程中,采用了右移操作进行数据截断。

这个操作可了不得,他会直接截断小数部分。例如3.1就会变成3。也就是说YUV这三个值都会因为这个数据阶段而偏小。

我们来解释一下YUV这三个值的意思:

  • Y(Luminance 或 Luma)

    表示亮度(Luminance),也就是图像的明亮程度。它包含了图像的黑白信息,取值范围通常在 0 到 255 之间,0 代表黑色,255 代表白色,中间的值对应不同程度的灰色。亮度分量是图像中最重要的部分,人眼对亮度的变化比颜色的变化更为敏感,在图像处理和视频编码中,亮度信息通常被更精确地保留和处理,以保证图像的整体视觉效果。

  • U(Chrominance Blue 或 Cb)

    代表蓝色色度(Chrominance Blue),也称为蓝色分量。它反映的是图像中蓝色部分与亮度的差异信息,用于表示颜色中的蓝色偏移量。U 的值描述了图像中蓝色分量相对于亮度的偏离程度,其取值范围一般也在一定的数值区间内,例如 - 128 到 127 等,0 表示没有蓝色偏移,正值表示蓝色分量多于平均水平,负值表示蓝色分量少于平均水平。

  • V(Chrominance Red 或 Cr)

    表示红色色度(Chrominance Red),即红色分量。它体现的是图像中红色部分与亮度的差异,用于衡量颜色中的红色偏移量。V 的取值范围与 U 类似,也是在一定区间内,0 代表没有红色偏移,正值表示红色分量多于平均水平,负值表示红色分量少于平均水平。通过 V 的值可以确定图像中红色的含量和分布情况。

而网络上有一张图就很好的概括了YUV偏向的结果:

commons.wikimedia.org/wiki/File:Y...

图片对应网站

由于RGB转YUV中的阶段操作导致YUV这三个的计算值都要比真实值偏小。而在上述的图片中我们可以看到:这种偏小带来的结果就是整体的显色效果都要向右下角靠拢。

显然,YUV 计算机整体偏小导致结果就是:变暗,变绿。

而大多数互联网公司例如贴吧,QQ的客户端在进行图片压缩算法的时候都采用的是安卓提供的这一套压缩图片的算法。

这也就导致了"电子包浆"的重灾区一般就集中在贴吧和QQ中。

而Google在2016年的4月19日才正式的修复了这个bug。在百度查询了一下对应的Android发布版本,也就是说Android7才消除了这个问题。

这个bug的修复很简单,在代码层面的表现为:把原本 Skia 库 YUV 转换代码全部删掉,把这个过程留给整个过程最底层的 libjpeg-turbo 库自己来做,并且用默认的 JDCT_ISLOW 方法代替 JDCT_IFAST 方法。

github.com/google/skia...

对应的PR

总结一下呢:就是在图片压缩的过程中需要先将RGB色彩空间转化为YUV色彩空间。但是在转化的过程中对小数的处理并不到位。导致计算出来的YUV比真实的YUV值要偏小。反映在图片上就是整体偏暗偏绿。

那么今天关于"图片为什么会有电子包浆"的内容就介绍到这里了。相信通过我的介绍,你已经大致了解了为什么会出现这种情况。希望我的文章可以帮到你。

你有没有这种"电子包浆"的图片呢?听说现在评论区可以发视频了。快在评论区里发出来让大家看看吧。

关注我,带你了解更多技术干货。

相关推荐
阿巴斯甜4 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker5 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95276 小时前
Andorid Google 登录接入文档
android
黄林晴7 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab19 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android