PNG文件格式详解
源文件地址:https://blog.mythsman.com/2015/12/08/1/
最近在看隐写术的时候经常需要研究图片文件的二进制文档格式,那么这就很有必要了解我们的图片文件究竟是如何保存的了,今天找了个时间看了下png文件的文档格式。总体还是挺麻烦的,不过毕竟不需要有什么要求,能了解即可。
概述
PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的“PNG’s Not GIF”,是一种位图文件(bitmap file)存储格式,读成“ping”。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可存储多到16位的α通道数据。PNG使用从LZ77派生的无损数据压缩算法。(说白了这就是一种方便的、适于网络传播的轻便图片文件格式)
特性
- 使用调色板技术可支持256种颜色的彩色图像。(必须的)
- 流式读/写性(streamability):图像文件格式允许连续读出和写入图像数据。(因此适于网络传播)
- 逐次逼近显示(progressive display):这种特性可使在通信链路上传输图像文件的同时就在终端上显示图像,把整个轮廓显示出来之后逐步显示图像的细节,也就是先用低分辨率显示图像,然后逐步提高它的分辨率。(类似马赛克逐渐消除的过程)
- 透明性(transparency):这个性能可使图像中某些部分不显示出来,用来创建一些有特色的图像。
- 辅助信息(ancillary information):这个特性可用来在图像文件中存储一些文本注释信息。(就是可以说一些废话)
- 独立于计算机软硬件环境。
- 使用无损压缩。(无损!)
- 可在一个文件中存储多幅图像。
文件结构
PNG图像格式文件由文件署名和数据块(chunk)组成。
文件署名域
8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值是:
| 十进制数 | 十六进制数 |
|---|---|
| 137 | 89 |
| 80 | 50 |
| 78 | 4e |
| 71 | 47 |
| 13 | 0d |
| 10 | 0a |
| 26 | 1a |
| 10 | 0a |
这个文件署名就是在《利用文件头标志判断文件类型》中提到的文件头标志了,很简单。
数据块
这里有两种类型的数据块,一种是称为关键数据块(critical chunk),就是必须要有的块;另一种叫做辅助数据块(ancillary chunks)。
每个数据块都由下表所示的的4个域组成。
| 名称 | 字节数 | 说明 |
|---|---|---|
| Length(长度) | 4字节 | 指定数据块中数据域的长度,其长度不超过(231−1)(231−1)字节 |
| Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码由ASCII字母(A-Z和a-z)组成 |
| Chunk Data(数据块实际内容 | 可变长度 | 存储按照Chunk Type Code指定的数据 |
| CRC(循环冗余检测 | 4字节 | 存储用来检测是否有错误的循环冗余码 |
其中CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的,可以看做一种校验码。
关键数据块
关键数据块中的4个标准数据块是:
(1) 文件头数据块IHDR(header chunk):
它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
文件头数据块由13字节,组成结构如下:
| 域的名称 | 字节数 | 说明 |
|---|---|---|
| Width | 4 bytes | 图像宽度,以像素为单位 |
| Height | 4 bytes | 图像高度,以像素为单位 |
| Bit depth | 1 byte | 图像深度:索引彩色图像:1,2,4或8 ;灰度图像:1,2,4,8或16 ;真彩色图像:8或16 |
| ColorType | 1 byte | 颜色类型:0:灰度图像, 1,2,4,8或16;2:真彩色图像,8或16;3:索引彩色图像,1,2,4或84:带α通道数据的灰度图像,8或16;6:带α通道数据的真彩色图像,8或16 |
| Compression method | 1 byte | 压缩方法(LZ77派生算法) |
| Filter method | 1 byte | 滤波器方法 |
| Interlace method | 1 byte | 隔行扫描方法:0:非隔行扫描;1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法) |
(2) 调色板数据块PLTE(palette chunk):
它包含有与索引彩色图像((indexed-color image))相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。真彩色的PNG数据流也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。结构如下:
|颜色|字节|意义|
|Red|1 byte||0 = 黑色, 255 = 红|
|Green|1 byte||0 = 黑色, 255 = 绿色|
|Blue|1 byte||0 = 黑色, 255 = 蓝色|
PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成,因此调色板数据块所包含的最大字节数为768,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。
对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。
(3) 图像数据块IDAT(image data chunk):
它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。
(4) 图像结束数据IEND(image trailer chunk):
它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。
如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:
00 00 00 00 49 45 4E 44 AE 42 60 82
不难明白,由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。
最后,除了表示数据块开始的IHDR必须放在最前面, 表示PNG文件结束的IEND数据块放在最后面之外,其他数据块的存放顺序没有限制。
辅助数据块
(比较杂,不需要全部了解透)
PNG文件格式规范制定的10个辅助数据块是:
- 背景颜色数据块bKGD(background color)。
- 基色和白色度数据块cHRM(primary chromaticities and white point)。所谓白色度是指当R=G=B=最大值时在显示器上产生的白色度。
- 图像γ数据块gAMA(image gamma)。
- 图像直方图数据块hIST(image histogram)。
- 物理像素尺寸数据块pHYs(physical pixel dimensions)。
- 样本有效位数据块sBIT(significant bits)。
- 文本信息数据块tEXt(textual data)。
- 图像最后修改时间数据块tIME (image last-modification time)。
- 图像透明数据块tRNS (transparency)。
- 压缩文本数据块zTXt (compressed textual data)。
数据块摘要
关键数据块、辅助数据块和专用公共数据块(special-purpose public chunks)综合下表中:
| 数据块符号 | 数据块名称 | 多数据块 | 可选否 | 位置限制 |
|---|---|---|---|---|
| IHDR | 文件头数据块 | 否 | 否 | 第一块 |
| cHRM | 基色和白色点数据块 | 否 | 是 | 在PLTE和IDAT之前 |
| gAMA | 图像γ数据块 | 否 | 是 | 在PLTE和IDAT之前 |
| sBIT | 样本有效位数据块 | 否 | 是 | 在PLTE和IDAT之前 |
| PLTE | 调色板数据块 | 否 | 是 | 在IDAT之前 |
| bKGD | 背景颜色数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
| hIST | 图像直方图数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
| tRNS | 图像透明数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
| oFFs | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
| pHYs | 物理像素尺寸数据块 | 否 | 是 | 在IDAT之前 |
| sCAL | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
| IDAT | 图像数据块 | 是 | 否 | 与其他IDAT连续 |
| tIME | 图像最后修改时间数据块 | 否 | 是 | 无限制 |
| tEXt | 文本信息数据块 | 是 | 是 | 无限制 |
| zTXt | 压缩文本数据块 | 是 | 是 | 无限制 |
| fRAc | (专用公共数据块) | 是 | 是 | 无限制 |
| gIFg | (专用公共数据块) | 是 | 是 | 无限制 |
| gIFt | (专用公共数据块) | 是 | 是 | 无限制 |
| gIFx | (专用公共数据块) | 是 | 是 | 无限制 |
| IEND | 图像结束数据 | 否 | 否 | 最后一个数据块 |
tEXt和zTXt数据块中的标准关键字:
| 关键字 | 说明 |
|---|---|
| Title | 图像名称或者标题 |
| Author | 图像作者名 |
| Description | 图像说明 |
| Copyright | 版权声明 |
| CreationTime | 原图创作时间 |
| Software | 创作图像使用的软件 |
| Disclaimer | 弃权 |
| Warning | 图像内容警告 |
| Source | 创作图像使用的设备 |
| Comment | 各种注释 |
一个例子
为了便于研究,我在本地找了个24x24像素的图片:

用十六进制打开后是这样的:
1 |
0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR |
接下来我们试着分析一下:
首先是八个字节的文件头标志,标识着png文件:
1 |
8950 4e47 0d0a 1a0a |
接下来的地方就是IHDR数据块了:
0000 000d说明IHDR头块长为13
4948 4452IHDR标识(ascii码为IHDR)
下面是IHDR数据块的实际内容
0000 0018图像的宽,24像素
0000 0018图像的高,24像素
08 表示色深,这里是2^8=256,即这是一个256色的图像
06 颜色类型,查表可知这是带α通道数据的真彩色图像
00 PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)
00 同上
00 非隔行扫描
e0 773d f8 CRC校验
以上分析了第一个IHDR块的内容,其他块的分析方法类似,比如接下来的就是tEXt块了,很简单,不做分析了。(当然这里还有重要的IDAT块,这是图像的实际内容)
最后得有个IEND数据块,这部分正如上所说,通常都应该是
00 00 00 00 49 45 4E 44 AE 42 60 82
由于我用的是vim打开,vim在文件最后都会恶心的自己加上0a换行,当然这并没有什么坏的影响。不过这也提醒了我们一个问题,既然在IEND块后面添加任何的字符都对文件的打开造成不了影响,那我们就可以在这里藏一些数据了(当然这种藏法很low)。。。
OK,这就是png文件的基本构造了。
PNG文件格式详解的更多相关文章
- BMP文件格式详解
BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广 ...
- PE文件格式详解,第一讲,DOS头文件格式
PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...
- PE文件格式详解,第二讲,NT头文件格式,以及文件头格式
PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) PS:本篇博客 ...
- PE文件格式详解,第三讲,可选头文件格式,以及节表
PE文件格式详解,第三讲,可选头文件格式,以及节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶可选头结构以及作 ...
- Carbondata源码系列(二)文件格式详解
在上一章当中,写了文件的生成过程.这一章主要讲解文件格式(V3版本)的具体细节. 1.字典文件格式详解 字典文件的作用是在存储的时候将字符串等类型转换为int类型,好处主要有两点: 1.减少存储占用空 ...
- DOS文件转换成UNIX文件格式详解
转:DOS文件转换成UNIX文件格式详解 由windows平台迁移到unix系统下容易引发的问题:Linux执行脚本却提示No such file or directory dos格式文件传输到uni ...
- OpenGL学习--05--纹理立方体--BMP文件格式详解(转载)
http://blog.csdn.net/o_sun_o/article/details/8351037 BMP文件格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称 ...
- Android逆向之旅---SO(ELF)文件格式详解(转)
第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...
- 音视频入门-11-PNG文件格式详解
* 音视频入门文章目录 * PNG 文件格式解析 PNG 图像格式文件由一个 8 字节的 PNG 文件署名域和 3 个以上的后续数据块(IHDR.IDAT.IEND)组成. PNG 文件包括 8 字节 ...
- Android逆向之旅---SO(ELF)文件格式详解
第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...
随机推荐
- python基础教程 变量/输入输出/if判断
python的运用越来越多.大数据经常被人谈及,数据从何而来?通过各个平台.app.网站数据的收集,分析,过滤,生成报告,这些都可以用python来处理,并且有很多成熟的库可以直接用了.那还不赶紧深入 ...
- InnoDB缓冲池预加载在MySQL 5.7中的正确打开方式
InnoDB缓冲池预加载在MySQL 5.7中的正确打开方式 https://mp.weixin.qq.com/s/HGa_90XvC22anabiBF8AbQ 在这篇文章里,我将讨论在MySQL 5 ...
- 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】
四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...
- vue中使用promise
init1(){ return new Promise((resolve, reject) => { let data={ dateStr:this.time }; api.get('url', ...
- Cartographer源码阅读(3):程序逻辑结构
Cartographer早期的代码在进行3d制图的时候使用了UKF方法,查看现有的tag版本,可以转到0.1.0和0.2.0查看,包含kalman_filter文件夹. 文件夹中的pose_track ...
- SpringMVC的Model ModeMap ModelAndView @ModelAttribute @SessionAttribute区分
Spring MVC整理系列(05)————Spring MVC配置解析及整合SpriSpring MVC之@ModelAttribute.@SessionAttributes以及Model的使用介绍 ...
- 监督学习之knn算法
1.1 KNN(K-Nearest Neighbor)工作原理: 存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类对应的关系.输入没有标签 ...
- Makefile中变量定义中末尾不能有空格
我在Makefile中添加了 ifndef EMASSDIR EMASSDIR=$(shell emassTop.py)endif 但是emassTop.py)后面不小心加入了空格,造成出现“Make ...
- WCF&AppFabric :异常消息: 内存入口检查失败
bug描述 发件人信息: System.ServiceModel.ServiceHostingEnvironment+HostingManager/31242459 异常: System.Servic ...
- What is the reason for - java.security.spec.InvalidKeySpecException: Unknown KeySpec type: java.security.spec.ECPublicKeySpec
支付中心Project重构完成,经过本地测试,并未发现问题.发布到测试环境后,测试发现请求光大扫码https接口时,出现了如下的异常: javax.net.ssl.SSLException: Serv ...