前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >为什么网络上一些表情包在反复传播之后会变绿?这就是传说中的“电子包浆”嘛?

为什么网络上一些表情包在反复传播之后会变绿?这就是传说中的“电子包浆”嘛?

作者头像
程序员牛肉
发布2025-02-04 13:31:16
发布2025-02-04 13:31:16
1300
举报

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

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

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

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

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

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

https://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偏向的结果:

https://commons.wikimedia.org/wiki/File:YUV_UV_plane.svg 图片对应网站

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

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

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

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

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

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

https://github.com/google/skia/commit/c7d01d3e1d3621907c27b283fb7f8b6e177c629d 对应的PR

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员牛肉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档