夜下客

繁体版 简体版
夜下客 > JS修炼法则 > 第17章 深入PNG格式

第17章 深入PNG格式

讲故事时间到了。

1.背景

上上周发布了简易的图片分割npm, 传入一个图片URL即可得到图片切片File数组。

当时的应用场景是: 为了解决页面首屏性能问题。

简单的运营页需要传背景图,但是一般背景图都比较大,大概 1M 左右,这就导致首屏时间较长(一般1M的加载+渲染要1000ms多),为了提升性能,基础侧提供图片切片能力、业务侧使用懒加载技术。

晚上的时候一个大哥问我, 一张PNG原图CDN压缩后大小是1.5M,拿到的切片数组第一张图大小是800KB,问我为啥会这样,大哥又追问了一句:如果用JPG格式会不会更好啊。

我脑子第一反应是, 众所周知PNG 比JPG 压缩效率更高。但我突然不知道个所以然了。

群哥在旁边突然来了句:“你知道PNG和JPG的存储是怎样的么?”

我:“没深入了解过”

群哥:“简单来说,PNG存储本质是一个MAP,这个MAP的value包含了所有RGB色值,PNG使用MAP的key,所以很多重复的地方可以用key去代替就好了。”

这种存储模式是索引彩色模式。GIF也采用该模式。

群哥:“而JPG是色值存储,它的每一个像素点都是RGB存储的。”

群哥:“就像我们写代码一样,对于重复率高的代码抽离成组件,可以减少整个项目的体积”

我:膜拜膜拜!!!

然后我就自己去搜索了下相关PNG 资料,简单如下。

后续的压缩都是指从原始图像压缩为 PNG/JPG 的过程。

2.定义

PNG, 便携式网络图型(Portable Network Graphics), 是一种采用无损压缩算法的位图格式。特点如下:

无损压缩, 体积小:采用LZ77 算法的派生算法,压缩比高。利用特殊的编码方法标记重复出现的数据,对图像颜色无影响。

LZ77算法是一种算法理论,而非具体代码实践。JPG 对图像亮度无影响, 压缩的是图像颜色中的蓝色和红色。

支持透明效果:对原图像定义256个透明层次, 消除锯齿边缘。GIF和JPG没有。

PNG32 支持透明效果, 剩下的两种PNG 类型也是不支持透明效果的。

索引彩色模式:采用8位调色板将RGB彩色图像转换为索引彩色图像。图像中保存的是颜色编号,每一编号对应一种颜色,图像的数据量也因此减少。

这就是群哥讲解的重点。JPG 图像中保存的是各个像素的彩色信息。

3.类型(3种)

PNG n数字n代表n bits , 表示使用2^n 大小来存储有一张图片的颜色种类, 即能存储2^n 种颜色。适用于存储颜色种类少的图片。

PNG8: 能存储256 种颜色。适用于存储颜色种类少的图片。

PNG24: 数字24代表3*8bits, 分别表示 R(红)、G(绿)、B(蓝), 能存储16777216 种颜色。

PNG32: 在PNG24的基础上增加了透明颜色, A(透明), 能存储16777216 种透明的颜色。

4.数据结构

它由一个8字节的PNG文件署名域(或理解为 header)以及3个以上的chunk组成。

如果你把PNG理解为HTTP请求, 那PNG文件署名域就是 header .

首先, 先来思考一下为什么有 「PNG文件署名域」?

PNG文件署名域的作用:识别该文件是不是PNG 文件。

该域的值为89504e470d0a1a0a(十六进制),(13780787113102610十进制),第一个字节0x89超出ASCII字符的范围,是为了避免被当做文本文件来处理。

所以,小结论:PNG 文件总是以89504e470d0a1a0a开头。

其次,为什么我要强调是「3个以上的chunk」?

最基础的PNG 文件包含IHDR、IDAT、IEND三个chunk。

每个 chunk 由4部

『加入书签,方便阅读』