文章目录
前奏
大概看了一下jpg的格式之后,再来一起看看png图片格式
概念
BMP文件总体上可以分为两部分组成,分别是PNG文件标志和数据块。其数据块分为两类:关键数据块和辅助数据块。
PNG文件的组成结构
PNG文件标志 |
---|
数据块(chunks) |
-
PNG文件标签
PNG文件标志由8个字节组成:89 50 4E 47 0D 0A 1A 0Ah
,其中50 4E 47对应的ASCII值是“PNG”
-
数据块
紧跟在PNG文件标志后面的是数据块(chunks),数据块分为两类:关键数据块和辅助数据块。 -
关键数据块在PNG文件中是必须有的,而辅助数据块是可选的;关键数据块由4部分组成:文件头数据块(IHDR),调色板数据块(PLTE),图像数据块(IDAT)和图像结束数据(IEND),其中调色板数据块(PLTE)根据图像的色深可选
-
辅助数据块(ancillary chunks)一共有14个,这些辅助类数据块包含了很多信息,辅助类数据块不是必须包含
PNG文件的关键数据块(critical chunks)组织顺序
数据块名称 | 允许多个数据块 | 位置 |
---|---|---|
文件头数据块(IHDR) | 不允许 | 第一个数据块 |
调色板数据块(PLTE) | 不允许 | 第二个数据块,可选 |
图像数据块(IDAT) | 允许 | 如果有调色板(PLTE),则是第三个数据块,如果没有调色板数据块(PLTE),则是第二个数据块。如果有多个数据块,则必须按图像数据连续存储 |
图像结束数据(IEND) | 不允许 | 最后一个数据块 |
PNG文件的辅助数据块(ancillary chunks)组织顺序
数据块名称 | 允许多个数据块 | 位置 |
---|---|---|
基色和白色点数据块(cHRM) | 不允许 | 在PLTE和IDAT之前 |
图像r数据块(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之前 |
建议调色板(sPLT) | 允许 | 在IDAT之前 |
物理像素尺寸数据块(pHYs) | 不允许 | 在IDAT之前 |
图像最后修改时间数据块(tIME) | 不允许 | 无限制 |
国际文本数据(iTXt) | 允许 | 无限制 |
文本信息数据块(tEXt) | 允许 | 无限制 |
压缩文本数据块 | 允许 | 无限制 |
PNG文件的数据块格式
PNG图像文件中每一块数据块的格式都是相同的,分别由四部分组成,格式如下:
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
Length(长度) | 4 | 指定数据块中的数据长度 |
Chunk Type Code(数据块类型码) | 4 | 数据块类型,例如IHDR,PLTE,IDAT等 |
Chunk Data(数据块数据) | Length | 存储数据 |
CRC(循环冗余检测) | 4 | 循环冗余码 |
CRC循环冗余码生成的计算方式是通过对Chunk Type Code
和Chunk Data
中的数据计算得到的,计算方式如下:
X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X+1
数据块含义
文件头数据块(IHDR)
文件头数据块(IHDR)它包含有PNG文件中存储的图像数据的基本信息,如图像的宽高,色深,颜色类型,压缩方式等。一个PNG文件只能有一个文件头数据块。
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
Width | 4 | 图像宽度,以像素为单位 |
Height | 4 | 图像高度,以像素为单位 |
Bit depth | 1 | 图像深度:索引彩色图像:1,2,4或8;灰度图像:1,2,4,8或16;真彩色图像:8或16 |
ColorType | 1 | 颜色类型:0:灰度图像,1,2,4,8或16;2:真彩色图像,8或16;3:索引彩色图像,1,2,4或8;4:带α通道数据的灰度图像,8或16;6:带α通道数据的真彩色图像,8或16 |
Compression method | 1 | 压缩方式(LZ77 变种算法) |
Filter method | 1 | 滤波器方法 |
Interlace method | 1 | 隔行扫描方法:0:非隔行扫描 1:Adam7(由Adam M.Costello 开发的7遍隔行扫描方法) |
调色板数据块(PLTE)
PNG
的调色板数据块(PLTE
)和之前介绍过的BMP
图像格式中的调色板类似,都是提供给8位色深以下的图像使用。PNG
的调色板由3个字节组成,每个字节分别表示红,绿,蓝三色的颜色值。
对于PNG图像文件来说,大于8位色深的图像,如真彩色图像也可以使用调色板,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像
一个PNG文件只能有一个调色板数据块,调色板数据块从下表0开始
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
btRed | 1 | 红色颜色值 |
btGreen | 1 | 绿色颜色值 |
btBlue | 1 | 蓝色颜色值 |
图像数据块(IDAT)
PNG的图像数据块(IDAT)存储图像的实际数据,相当于BMP图像的图像数据,由于PNG可包含多幅图像,所以PNG的图像数据块可能是一副图像的数据组成,也可能是多幅图像的数据组成。
图像数据块中的图像数据可能是经过变种的LZ77压缩编码 DEFLATE压缩的,关于DEFLATE详细介绍可以参考《DEFLATE Compressed Data Format Specification version 1.3》,网址http://www.ietf.org/rfc/rfc1951.txt
图像结束数据(IEND)
PNG的图像结束数据(IEND)用来标记PNG文件结束,并且必须要放在文件的尾部。一般情况下,所有PNG图像结束数据(IEND)的十六进制数值都是一样的,具体的数值如下:
00 00 00 00 49 45 AE 44 4E 62 60 82
PNG的辅助数据块(ancillary chunks)一共有14个,可以分为5类,可参考http://www.w3.org/TR/REC-png.html
实例
用这张图片吧,O(∩_∩)O哈哈~
PNG的文件标志
首先分析PNG的文件标志。根据PNG文件的定义,从文件头开始前8字节数据是PNG文件的标志
89 50 4E 47 0D 0A 1A 0A
文件头数据块(IHDR)
接下来应该就是PNG文件的数据块结构了,按照前面对PNG文件结构的理解,第一个数据块是文件头数据块(IHDR)数据块,定义了PNG文件的宽高,色深,压缩方法等参数
PNG文件使用Big-Endian
顺序存储数据,不需要反转字节数据
十六进制值 | 描述 |
---|---|
00 00 00 0D | 文件头的数据长度,00 00 00 0D=13 |
49 48 44 52 | 数据块类型标志,49 48 44 52的ASCII值等于IHDR |
00 00 07 7F | 图像的宽度,00 00 07 7F=1919 |
00 00 03 90 | 图像的高度,00 00 03 90=912 |
08 | 色深,表示2的8次幂等于256色 |
06 | 06表示索引图像 |
00 | 00表示使用Deflate压缩编码压缩图像数据 |
00 | 00表示为将来使用更好的压缩方式预留 |
00 | 00表示非隔行扫描 |
39 7C BB 5A | 39 7C BB 5A 表示CRC |
最后这个CRC字段的值为39 7C BB 5A
,这个CRC值是按照从数据块类型标志字段到CRC字段前一字节的数据计算而来的,即使用数据
49 48 44 52 00 00 07 7F 00 00 03 90 08 06 00 00 00
(CRC(循环冗余校验)在线计算)http://www.ip33.com/crc.html
利用工具算了一下,CRC正确
标准RPG颜色数据块(sRGB)
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
十六进制值 | 描述 |
---|---|
00 00 00 01 | 标准RPG颜色数据块的长度,00 00 00 01=1 |
73 52 47 42 | 数据块类型标志,73 52 47 42的ASCII值等于sRGB |
00 | |
AE CE 1C E9 | CRC值 |
图像r数据块(gAMA)(PNG解码时进行gamma校正信息)
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
十六进制值 | 描述 |
---|---|
00 00 00 04 | 图像r数据块(gAMA)数据块的长度,00 00 00 04=4 |
67 41 4D 41 | 数据块类型标志,73 52 47 42的ASCII值等于gAMA |
00 00 B1 8F | gamma校正信息 |
0B FC 61 05 | CRC值 |
物理像素尺寸数据块(pHYs)
字段名 | 大小(单位:字节) | 描述 |
---|---|---|
physPixelPerUnitX | 4 | 每个单位多少像素。x轴 |
physPixelPerUnitY | 4 | 每个单位多少像素。y轴 |
UnknownUnit,Meter | 1 | 枚举类型,UnknownUnit=0,表示只定义了像素IX暗示的比例,未定义实际像素大小。枚举类型,Meter=1,表示定义单位为米 |
十六进制值 | 描述 |
---|---|
00 00 00 09 | 物理像素尺寸数据块的长度,00 00 00 09=9 |
70 48 59 73 | 数据块类型标志,70 48 59 73的ASCII值等于pHYs |
00 00 12 74 | X轴上每米像素的数量,00 00 12 74=4724 |
00 00 12 74 | Y轴上每米像素的数量,00 00 12 74=4724 |
01 | Meter=1,将单位定义为米 |
DE 66 1F 78 | CRC值 |
图像数据块(IDAT)
十六进制值 | 描述 |
---|---|
00 00 FF A5 | 图像数据块的长度,00 00 FF A5=65445 |
49 44 41 54 | 数据块类型标志,49 44 41 54的ASCII值等于IDAT |
78~8B | 图像数据块,一共65445字节,使用变种的LZ77压缩过 |
E5 50 2E 8B | CRC值 |
图像结束数据块(IEND)
十六进制值 | 描述 |
---|---|
00 00 00 00 | 图像数据块的长度,00 00 00 00=0 |
49 45 AE 44 | 数据块类型标志,49 45 AE 44的ASCII值等于IEND |
AE 42 60 82 | CRC值 |
构建一张png框架图
改长度
FF A5改成00 00
填充CRC值
算出为 35 AF 06 1E
加图像结束数据块(IEND)
保存
IDAT数据块长度为0
注意:png的idat的长度不能为0
否则打不开