探索 JPG 和 PNG 图片的压缩表现、算法与应用
前段时间做了些展示页,工作时需要给到切图给前端。以我的习惯,每次都会导出 PNG 并压缩后才交付给前端。有一天我突然想到:
为什么我每次切图时下意识都是会提供 PNG 格式给开发,而不是使用 JPG 格式的图片?这是什么时候开始的习惯?
回想起来应该是我刚刚进职场的时候,在一些设计文章里听过的说法:
- PNG 图片支持透明通道,适用场景比 JPG 要更加宽广,无脑 PNG 即可;
- PNG 图片支持 "无损压缩",所以图像质量会比 JPG 好一些。
第一点毋庸置疑,但对于第二点我是有点怀疑的:PNG 图片的质量真的在任何时候都比 JPG 要高吗?并且更想知道所谓的 "无损压缩" 是什么,真有这么厉害的技术?所以我打算花点时间做下研究,顺便将研究结果分享给其他团队的设计师们。
这篇文章是一篇在团队月度分享会的记录,分享会内容主要是在回答这个问题:
JPG 和 PNG 分别适合储存什么类型的图片?
回答完这个问题后,我会简单介绍下 JPG 和 PNG 图片压缩机制。正是因为 JPG 和 PNG 这两种图片格式的压缩机制的不同才导致适合储存不同类型的图片。
以及扩展一下思路,会介绍一个我已经实际工作用过的方法:通过 CSS 的混合模式节省网页图片资源。
一、图片压缩分析
分析方法
这次我用了三种类型的图片进行分析,都是我在实际设计工作中有可能导出成位图交付给前端开发的图片类型:
- 颜色丰富的 Banner 图:测试压缩算法在细节保持方面的表现
- 过渡柔和的背景图:测试压缩算法在处理低色彩复杂度时的表现
- 界面设计图:测试压缩对大色块、文字和边缘清晰度的影响
具体的分析过程:拿三个在设计工作中常用到的图片类型(相同尺寸、均无透明通道)进行压缩,以对比 JPG & PNG 图片在压缩前后的表现。分两个维度进行对比:图片体积和图像质量。
分析结果
一、图片体积对比
由上图对比可以比较直观的看到,前两个类型(颜色丰富的 Banner 图、过渡柔和的背景图)在图片体积上,JPG 格式图片的体积要比 PNG 格式的图片体积小得多。
通过这一轮对比,我们可以得出结论:
- 画面颜色丰富、颜色过渡比较细腻柔和的图片,JPG 图片的体积比 PNG 的更小;
- 画面颜色越丰富,JPG 图片越能节省空间;
- 颜色数量较少时,PNG 图片的体积比 JPG 图片的更小;
- PNG 图片在压缩后,色块、文字的边缘的质量会比 JPG 图片要好得多。
二、图像质量对比
对比一:颜色丰富的 Banner 图
这一轮我们会放大图片的局部,对比 JPG 和 PNG 图片在经过压缩后,图像质量的区别。
在颜色丰富的图像中,JPG 图片的颜色过渡质量比 PNG 好得多,即便是压缩过后也能保持柔和的过渡。反观 PNG 图片,则是出现了明显的色块。
在文字、边缘的展示方面,PNG 图片则比 JPG 图片好一些。PNG 图片保持了原本清晰、锐利的边缘,而 JPG 图片则在处理边缘时有些许杂色。
对比二:过渡柔和的背景图
这是一个令人意外的结果,在图像内容比较简单,仅仅只有一些色彩过渡的时候,JPG 和 PNG 图片的质量都很接近。只有在放大很多倍的时候才能看到 PNG 的图片过渡效果比 JPG 要差一些,还是出现了和前一种类型类似的色块现象。
为了探究得更深入些,我在这里用了一张暗色系且过渡柔和的背景图进行同样的压缩测试,这次的测试结果对比会明显很多。
在深色系且有柔和过渡的图片当中,JPG 图像的质量明显比 PNG 要高。如上图所示,PNG 图片的色块和噪点已经比较明显了,而 JPG 仍然保持较柔和的过渡。
对比三:界面设计图
在对比界面设计图时可以看到,PNG 格式的图片在处理色块边缘、文字边缘时都比 JPG 图片要好得多,边缘很清晰锐利,甚至和压缩前的原图没有什么分别。
三、总结
经过上述对三种不同类型图片的图片体积、画面质量对比后,我这里总结出了以下规律:
- JPG 格式适用于颜色丰富,过渡柔和,有丰富的颜色渐变和复杂的视觉元素的图片。比如网站 Banner、大场景、3D 渲染图、摄影图片等,此时用 JPG 图片可以得到体积小且颜色漂亮的图片;
- PNG 格式适用于颜色数量少,色块切割明显的图片。比如界面、扁平插画、Logo,带有文字的图片等,此时用 PNG 图片可以得到体积小,色彩准确且边缘清晰的图片。
二、图片压缩过程
这一章会探索 JPG & PNG 图片的压缩过程,这也是导致上文提到 JPG 和 PNG 压缩后图像差异的原因。
JPG 图片压缩过程
JPG 图片压缩过程主要有以下几步:
- 色彩空间转换(预处理)
- 下采样(有损压缩)
- 分块和离散余弦变换(预处理)
- 量化(有损压缩)
- 编码
- 存储
在整个压缩过程中会进行两次预处理和有损压缩,分别是第1、2步和第3、4步。其他步骤与图像质量之间的关系不大,所以我这里就只介绍这两次的预处理和压缩。
第一次预处理和压缩(色彩空间转换和下采样)
我们设计师平常接触到的 "RGB" 或 "CMYK" 色彩空间,一个字母代表一种颜色,比如 "RGB" 意味着 "红绿蓝","RGB" 的色值代表红色、蓝色、绿色分别占多少。
而压缩工具拿到 JPG 图片后,会先将图片转换为一个叫 "YCbCr" 的色彩空间。其中 "Y" 代表了这张图片的亮度信息,而 "Cb/Cr" 分别代表图片中蓝色和红色与亮度 "Y" 的差值。经过这种转换,可以针对性地保留更多的亮度信息,而减少色度信息。简单来说就是能够让人眼难以感知到的方式来减少图像中的色彩信息,减少图片文件体积。
色彩空间转换之后,会进行一个叫 "下采样" 的压缩动作。维持亮度信息的同时,统一处理每个 2x2 的像素区块的色度信息(比如在一个 2x2 区块内 4 个像素在色彩上会被统一处理,看起来拥有相同的色度,但明度是不同的)
第二次预处理和压缩(分块、离散余弦变换和量化)
分块、离散余弦变换指的是会将图像分成多个 8*8 像素的色块,然后将其从像素域转换成频率。转换成频率域的意思是能够让电脑分辨图像中的:
- 高频成分。颜色变化剧烈的部份,如色块、文字的边缘;
- 低频成分。颜色变化平缓的部份,如下图所示的黄色渐变。
而量化则是利用了人类视觉对于图像中的高频变化不是很敏感这一点,通过减少高频区域的数据量,同时在低频区域保持一定精度,让人感觉到图片仍然很清晰。
简单来说,就是压缩算法知道图像里哪些部分的色彩过渡比较缓和,哪些部分的色彩过渡是强烈的,然后对色彩过渡比较强烈的部份使用较高的压缩率。
结论
所以正如前面对比分析时看到的结果那样,JPG 图片对于色彩丰富的图片的压缩效果比较好,因为 JPG 的压缩算法会根据人眼的特点来优化图片的不同区域。
PNG 图片压缩过程
PNG 图片的的压缩过程主要有以下几步,其中只有前三步对图像画质有影响,这里只介绍前三步:
- 量化(有损压缩)
- 过滤器选择(预处理)
- DEFLATE 压缩(无损压缩)
- 合成输出
量化
第一步的量化是根据图像的需求选择合适的颜色类型和位深度,简单来说就是直接减少图片的颜色数量。这是最直接有效的压缩方式,同时也对图像质量损耗较大。
下图可以看到一个图像从 24 位(能储存 1677 万种颜色,又称真彩色)减少到 8 位色(能储存 256 种颜色,又称索引色)时,会出现色带现象 (Color Banding)
过滤器选择和 DEFLATE 压缩
这一步才是 PNG 图片的无损压缩。首先会先扫描 PNG 图片的每一行像素,然后以一种新的方式计算每个像素格子的颜色值。比如一个叫 "Sub" 的过滤器,每个像素值是通过当前像素值减去该像素左边像素值得到的;一个叫 "Average" 的过滤器,每个像素值是通过当前像素值减去当前像素左边和上方像素值的平均值得到的。
而 DEFLATE 压缩,这里会用到的方式有很多,比如 LZ77 编码和哈夫曼编码,这里不展开说明了,简单来说就是对过滤过的数据以更优的方式编码,达到减少文件大小的目的。
结论
基于上文提到的过滤器,不难想象到这种无损压缩的方式对于颜色分明的图片 - 比如纯色图标,App 界面截图,扁平插画等 - 很有用,因为像素之间存在细微差异的地方不多,画面上都是大色块居多。
三、其他解决方案
前面提到了很多跟图像压缩相关的事情,这些都是与网页加载优化息息相关的。正好我前段时间做了一个需求,我让前端帮忙做了一件事来节省了大量的图片素材,也算是一次网页加载优化的小案例。
我的设计方案里需要用到八种主题色来作为对卡片的区分,然后我会给这八种主题色的卡片提供一个有简单渐变图像的背景图用以装饰画面,让其过渡不太生硬。设计稿如下图:
如果按常规的做法和给予上文的调研,我将要提供八张代表不同颜色主题且经过压缩的 JPG 图片给到前端。但是在实际工作中,我只提供了一张灰色的背景图,然后让前端帮忙用 CSS 的颜色叠加 "Screen" 方式来给这张灰色图片上色,达到的效果是与设计稿一模一样的。
下面这张图或许能直接地解释其原理,我先提供一个灰色的素材图,里面只有黑和白之间的明度变化,然后前端会写一个颜色块在这个图片上面,最后使用 CSS 属性 background-blend-mode: screen;
将这张灰色的图片和色块进行叠加,得到了与主题色对应的背景图。
最终我仅用一张素材图实现了原本需要八张素材图才能实现的效果,成就感满满!
总结
这次做的调研确实打破了我从业以来多年的错误观念,现在我清晰地知道了:
- JPG 和 PNG 适合储存的图像是不一样的;
- JPG 和 PNG 的压缩算法导致了图片在压缩后的表现不一样。
虽然这些跟设计技能无关,但也算是一种视野的开拓吧。
这次的分享会是从一个 UI 设计师的角度去探索的,实际上我在 SHEIN 的工作更多是以交互设计师的角色去完成的,我已经有计划在之后的文章中分享更多交互设计的案例,读者们敬请期待吧。