png文件格式详解,获取文件的修改时间,创作时间

时间:2021-02-17 00:20:59

http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm
http://www.360doc.com/content/11/0428/12/1016783_112894280.shtml
https://www.cnblogs.com/lidabo/p/3701197.html
http://blog.csdn.net/bisword/article/details/2777121
http://blog.csdn.net/hherima/article/details/45847043
http://twt35twt.iteye.com/blog/1351626

http://blog.csdn.net/Blues1021/article/details/45007943 (good)
http://blog.csdn.net/u014646950/article/details/51144476

code一个png文件,大致了解下png文件的格式

对于一个PNG文件来说,其文件头总是由位固定的字节来描述的:

十进制数 137 80 78 71 13 10 26 10
十六进制数 89 50 4E 47 0D 0A 1A 0A

其中第一个字节0x89超出了ASCII字符的范围,这是为了避免某些软件将PNG文件当做文本文件来处理。
文件中剩余的部分由3个以上的PNG的数据块(Chunk)按照特定的顺序组成,因此,一个标准的PNG文件结构应该如下:

PNG文件标志|PNG数据块|...|PNG数据块

PNG数据块(Chunk)
PNG定义了两种类型的数据块,
一种是称为关键数据块(critical chunk),这是标准的数据块,
另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。

键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。
虽然PNG文件规范没有要求PNG编译码器对可选数据块进行编码和译码,但规范提倡支持可选数据块。

下表就是PNG中数据块的类别,其中,关键数据块部分我们使用 (!) 加以区分。
PNG文件格式中的数据块

数据块符号 数据块名称 多数据块 可选否 位置限制
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(!) 图像结束数据 否 否 最后一个数据块

这里要补充一个iCCP

为了简单起见,我们假设在我们使用的PNG文件中,这4个数据块按以上先后顺序进行存储,并且都只出现一次。

数据块结构:
PNG文件中,每个数据块由4个部分组成,如下:

名称 字节数 说明
Length (长度) 4字节 指定数据块中数据域的长度,其长度不超过(2^31-1)字节
Chunk Type Code (数据块类型码) 4字节 数据块类型码由ASCII字母(A-Z和a-z)组成
Chunk Data (数据块数据) 可变长度 存储按照Chunk Type Code指定的数据
CRC (循环冗余检测) 4字节 存储用来检测是否有错误的循环冗余码

下面,我们依次来了解一下各个关键数据块的结构吧

IHDR
文件头数据块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或8
4:带α通道数据的灰度图像,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遍隔行扫描方法)

PLTE
调色板数据块PLTE(palette chunk)包含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。

颜色 字节 意义
Red 1 byte 0 = 黑色, 255 = 红
Green 1 byte 0 = 黑色, 255 = 绿色
Blue 1 byte 0 = 黑色, 255 = 蓝色

对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数
(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。
真彩色图像和带α通道数据的真彩色图像也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。

IDAT
图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。

IEND
图像结束数据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

拿到一个png文件之后,可以把辅助的

由于PNG中规定除关键数据块外,其它的辅助数据块都为可选部分,因此,有了这个标准后,我们可以通过删除png文件中所有的辅助数据块来减少PNG文件的大小,
只保留IHDR、PLTE、IDAT和IEND数据块。
(当然,需要注意的是,PNG格式可以保存图像中的层、文字等信息,一旦删除了这些辅助数据块后,图像将失去原来的可编辑性。)

因为计算CRC需要一些时间,但对于字节较少的区块一般可以忽略不计。比如对IDAT数据块做CRC校验。

==================================

对tIME进行分析:

png文件格式详解,获取文件的修改时间,创作时间

根据数据块的组成规则,可以知道

选中的7个字节存储的数据即为 文件的修改时间

大概猜测时间的存储方式为:

1,2字节为 年份   0x070xE1 为 2017

3字节为 月            0x04 表示4月

4字节为 日            0x05 表示5号

5字节为 时            0x0A 表示10时

6字节为 分            0x1E表示30分

7字节为 秒            0x2C表示44秒

=====================================================

文件的创建时间,参考:

http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm

chunk类型的详细说明,参照 PNG文件格式白皮书。

tEXt的说明:

https://www.w3.org/TR/2003/REC-PNG-20031110/#11tEXt

使用WinHex查看一个包含创作时间的png文件:

png文件格式详解,获取文件的修改时间,创作时间

可以看到创作时间是 2016.1.20"