认识PNG (一)
Png是一种图形文件的存储格式 portable network graphics(可移植性网络图形)的缩写,读成“ping”(来自百度百科)。Png文件格式是网络上广泛使用的应用格式。
PNG是我们在前端开发中使用的比较多的一种图像文件格式,这种文件的最初的设计的目的就是为了替代gif(专利问题)和tiff(标签图像文件格式Tagged Image File Format,平常接触的比较少,主要用在图像处理应用、比如QuarkXPress和Adobe InDesign的桌面印刷、页面排版应用,扫描、传真、文字处理、光学字符识别,目前Adobe控制它的规范)。
特性:
因为是针对替代gif和tiff而设计的,所以的他的特点也是显而易见的,额,没有专利纠纷,格式相对简单,体积小能够保持较丰富的画质,完全针对于当时较慢的互联网设计的,有保留了gif和tiff的一些优点。那么他有那些具体的特点呢:
- 支持256色调色板
- 支持datastream,图像文件格式允许连续读出和写入图像数据,这个特性很适合在通信过程中使用。
- 逐次逼近显示,这种特性可使在网络传输过程中可以显示模糊的图像,然后逐步显示图像细节。
- 透明效果
- 辅助数据块
- 无损压缩,体积小。
- 独立于计算机软硬件环境
- 索引彩色模式
- 每个像素为48位的真彩色图像。
- 每个像素为16位的灰度图像。
- 可为灰度图和真彩色图添加α通道。
- 添加图像的γ信息
文件存储结构
1 png-8和png-24
在我们平常的切片中会遇到png-8 和 png-24两种格式的png,那么这种有什么区别呢?其最大的区别是PNG-24是用24位(bit)来保存一个像素值,是真彩色,而PNG-8是用8位(bit)索引值来在调色板中索引一个颜色,因为一个索引值的最大上限为2的8次方既256,故调色板中颜色数最多为256种。
其实PNG有5中类型:灰度,真彩色,索引色,带alpha通道的灰度,带alpha通道的真彩色。
在ps可以直观的看到调色板的原理:

2 文件存储结构

2.1 存储结构
如上图。
Png文件总体上分两部分,文件标示和数据块(chunks)。
关键数据块一个png文件必须有的结构,而辅助数据块存储一些附加信息,不是必须的的。正是因为这一点,很多游戏在优化时,去除游戏资源包中的PNG图片的辅助数据块就是一个很不错的方法。
需要注意的一点是:PNG图像格式使用Big-Endian顺序存储数据,网络字节序,也就是在内存结构中,高位字节和低位字节是顺序排列的(虽然按照地址老说,高位字节在低位地址)。这点是看明白pnglib中read png的一个基础。
2.2 PNG文件标示
所有的png文件开头都有相同的标示(signature),固定的8个字节:
对应的ASCI码是
,这个8个字节的出现标示下面的数据是由IHDR数据块开始以IEND数据结束的PNG数据流。
2.3 数据块结构
紧跟在文件标示后面的就是图像数据块。图像数据块(chunk)有很多类型,分为关键数据块(critical chunk)和辅助数据块(ancillary chunk)两大类。关键数据块是PNG文件必须的,辅助数据块是可选的。所有数据块都有相同的结构,如下图:

|
字 段 名 |
size(单 位:字节) |
描 述 |
|
Length(长度) |
4(无符号) |
Chunk Data的数据长度 ,不包括Length 、Chunk Type Code、 CRC。 |
|
Chunk Type Code (数据块类型字符) |
4 |
数据块类型,例如 IHDR、PLTE、IDAT等。这里需要注意的是chunk type的命名是由规范。(对自由扩展的PNG开发者来说需要仔细理解) |
|
Chunk Data(数据块数据) |
Length|0 |
图像数据 |
|
CRC(循环冗余检测) |
4 |
循环冗余码(ISO 3309)(计算的是 chunk type code+chunk data) |
示例:

关键数据块包括:文件头数据块(IHDR),调色板(PLTE),图像数据块(IDAT),图像结束数据块(IEND),其中调色板在png-24是可选的。
|
数据块名称 |
说 明 |
允许多个 数据块 |
位 置 |
|
|
文件头数据块(IHDR) |
|
不允许 |
第一个数据块 |
|
|
调色板数据块(PLTE) |
|
不允许 |
第二个数据块,可选 |
|
|
图像数据块(IDAT) |
Lw77变种压缩算法 |
允许 |
如果有调色板数据块(PLTE),则是第三个数据块,如果没有调色板数据块(PLTE),则时第二个数据块。如果有多个图像数据块,则必须按图像数据连续存储 |
|
|
图像结束数据(IEND) |
|
不允许 |
最后一个数据块 |
|
辅助数据块相关说明:
|
数据块名称 |
说 明 |
允许多个 数据块 |
位 置 |
|
|
基色和白色点数据块(cHRM) |
色彩(空间)管理相关 |
不允许 |
在PLTE和IDAT之前 |
|
|
图像γ数据块(gAMA) |
|
不允许 |
在PLTE和IDAT之前 |
|
|
ICCP(iCCP) |
|
允许 |
在PLTE之后IDAT之前如果有iCCP,则无sRGB |
|
|
样本有效位数据块(sBIT) |
|
不允许 |
在PLTE和IDAT之前 |
|
|
标准RPG颜色(sRGB) |
|
不允许 |
在PLTE之后IDAT之前如 果有sRGB,则无iCCP |
|
|
背景颜色数据块(bKGD) |
|
不允许 |
在PLTE之后IDAT之前 |
|
|
图像直方图数据块(hIST) |
|
不允许 |
在PLTE之后IDAT之前 |
|
|
图像透明数据块(tRNS) |
调色板中一个实体的透明度 |
不允许 |
在PLTE之后IDAT之前 |
|
|
物理像素尺寸数据块(pHYs) |
|
不允许 |
在IDAT之前 |
|
|
建议调色板(sPLT) |
|
允许 |
在IDAT之前 |
|
|
图像最后修改时间数据块(tIME) |
年月日时分秒(UTC) |
不允许 |
无限制 |
|
|
国际文本数据(iTXt) |
|
允许 |
无限制 |
|
|
文本信息数据块(tEXt) |
|
允许 |
无限制 |
|
|
压缩文本数据块(zTXt) |
|
允许 |
无限制 |
|
辅助数据块有很多为了支持复杂的颜色空间管理很对调色板的扩展,比如cHRM,sBIT等。它们在png文件的顺序是有一定规定的。和颜色管理相关的一般在PLTE之后IDAT之前。其他文本信息,比如tIME,tEXt则是无限制的,也就是可以和其他数据块任意顺序。
2.4 IHDR
它包含有PNG文件中存储的图像数据的基本信息,如图像的宽高、色深、颜色类型、压缩方式等。一个PNG文件只能有一个文件头数据块,下表列出了文件头数据块(IHDR)中各字段的含义。
|
字段名 |
大小(单 位:字节) |
描 述 |
示 例 |
|
Width |
4 |
图像宽度,以像素为单位 |
0x3c = 60px |
|
Height |
4 |
图像高度,以像素为单位 |
0x78 = 120px |
|
Bit depth |
1 |
图像深度: 索引彩色图像:1,2,4或8 灰度图像:1,2,4,8或16 真彩色图像:8或16 |
0x8 = 真彩色图像 |
|
ColorType |
1 |
颜色类型: 0:灰度图像,1,2,4,8或16 2:真彩色图像,8或16 3:索引彩色图像,1,2,4或8 4:带α通道数据的灰度图像,8或16 6:带α通道数据的真彩色图像,8或16 |
0x06 =带α通道数据的真彩色图像 |
|
Compression method |
1 |
压缩方法(LZ77变种算法) |
|
|
Filter method |
1 |
滤波器方法,png标准中定义了5中滤波器。 0:none(无过滤) 1:sub(当前值减去左侧像素的值) 2 :up(当前值减去上方像素的值) 3:average(减去左侧和上方像素的平均值) 4:paeth(替换上方,左边或者上方的左边像素值,并重新以Alan Paeth命名) (后续研究) |
|
|
Interlace method |
1 |
隔行扫描方法: 0:非隔行扫描 1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法) |
2.5 调色板(PLET)
一个PNG文件只有一个调色板数据块。
调色板数据类似一个数组,每个元素包括btRed,btGreen,btBlue三个字段。
调色板的索引从0开始。
|
字段名 |
大小(单 位:字节) |
描 述 |
|
btRed |
1 |
红色颜色值 |
|
btGreen |
1 |
绿色颜色值 |
|
btBlue |
1 |
蓝色颜色值 |
调色板索引原理图:

2.6图像数据块(IDAT)
PNG的图像数据块(IDAT)存储图像的实际数据,存储的是图像数据,由于PNG可包含多幅图像,所以PNG的图像数据块可能是由一幅图像的数据组成,也可能是由多幅图像的数据组成。(gif也可以包括多幅图像)
图像数据块中的图像数据可能是经过变种的LZ77压缩编码DEFLATE压缩的。
(解压后的数据结构(data layout)需要继续研究。)
我们知道的图像是由像素组成,像素实际上是真实世界的色彩采样(sample)。图像数据中每个像素的色深和颜色分值的关系:

2.7 图像结束数据(IEND)
PNG的图像结束数据(IEND)用来标记PNG文件结束,并且必须要放在文件的尾部。和png文件标示是对应的,一个开始一个结尾。一般情况下,所有PNG图像结束数据(IEND)的十六进制数值都是一样的,具体的数值如下:

2.8贴吧中使用的PNG的包含的数据块(以frs/pb右侧我的应用-添加应用的背景图为例):

3 PNG应用
3.1 内存计算
图片在内存占用取决于图像的尺寸和像素位数。
对于一张100*100的png-24的图片,其内存占用 = 100*100*4 * 8 /8 bytes = 40000bytes = 39.0625 kb
3.2 Png文件的加载过程
一张100*100的png-24的图片为例,

- 读取图片文件(消耗图片大小内存,3.21k)
- 解析PNG数据(编码后的内存大小如5.1计算为39k)
- 释放3.21k的图片内存(已经获得编码后的png)
- 渲染PNG (这个还需要验证)
- 释放内存。
注意,这个过程不是必然的顺序执行,释放内存的实际是有系统决定的,会很快,但是不一定是立即执行。 所以内存会瞬间飙升然后稳定。(需要验证)
3.3 CRC计算
CRC是循环冗余检测的缩写,因为这种算法简单易于硬件实现,一般用在数据通信的检测上,冗余码附加在信息码上,验证信息码是否有丢失。
在png中CRC计算的是数据块类型ChunkType和ChunkType。
这种算法需要一个生成多项式G(n),需要计算的数据多项式N(k)
一般的冗余码的位数是r= n-1,
冗余码 R = (N(k)<<r)%G(n)
PNG使用生成多项式是:
=(1 0000 0100 1000 0001 0001 1001 1011 0101)
= 1 04 81 19 b3
4 PNG优化
4.1 去掉版本和联系信息(辅助数据块)
每张图片可以节省大概0.8k,(png,其他格式待研究)。
贴吧首页43个png请求,大概可以节省流量43*0.8k = 34k
Frs(李毅) 49个png请求,大概可以节省流量49*0.8k = 39k

极端性的优化扫描每个png图片,去掉png-24所有的辅助数据块。(代码开发中)
也可以使用OptiPNG和pngcrush优化压缩。
从版权上来说,这个去掉月否有待商榷。
4.2 尽量减少单张png的高度和宽度
减少内存占用,提高机器渲染速度

去掉不必要的透明像素,如果png不使用过滤器也将会占用不必要的硬盘空间和流量。
参考资料:
PNG技术标准:http://www.w3.org/TR/2003/REC-PNG-20031110/
Libpng:http://www.libpng.org/pub/png/libpng.html
关于DEFLATE详细介绍可以参考《DEFLATE Compressed Data Format Specification version 1.3》, http://www.ietf.org/rfc/rfc1951.txt 。


浙公网安备 33010602011771号