PNG文件的解析

png是一种采用无损压缩算法的位图格式,其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。 

一  PNG文件结构

PNG文件由文件署名域(8字节)和最少3个数据块(Chunk)按照特定的顺序排列而成。 

数据块分为两类:

关键数据块(Critical Chunk):必须包含的数据块。

辅助数据块(Ancillary Chunk):可选的数据块。

png文件署名域png数据块png数据块.......png数据块

二  PNG文件的标志

8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值如下:

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

三  PNG文件的数据块

PNG文件有两种类型的数据块。关键数据块(critical chunk)和辅助数据块(ancillary chunks)。每个数据块由4个部分组成。

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

1.关键数据块有:

(1)文件头数据块IHDR(header chunk)

包含PNG文件里存储的图像数据的基本信息,作为第一个数据块出现在PNG数据流中,一个PNG数据流有且仅有一个文件头数据块。IHDR数据块的Chunk type code:0x49 48 44 52(ASCII码“IHDR”),标识该块类型

域的名称字节数说明
width4图像宽度
height4图像高度
bit depth1

图像深度:

索引彩色图像:1,2,4或8

灰度图像:1,2,,4,8或16

真彩色图像:8或16

color type1

颜色类型:

0:灰度图像,1,2,4,8或16

2:真彩色图像,8或16

3:索引彩色图像,1,2,4或8

4:带α通道数据的灰度图像,8或16

6:带α通道数据的真彩色图像,8或16

compression method1压缩方法(LZ77派生算法)
filter method1滤波器方法
interlace  method1

隔行扫描方法:

0:非隔行扫描

1:Adam7(由Adam M.Costell开发的7遍隔行扫描方法)

(2)调色版数据块PLTE(paltte chunk)

它包含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像有关,使得图像深度较小的图像,可以使用索引号来正确表示颜色。它要放在图像数据块(image data chunk)之前。PLTEPLTE数据块是定义图像的调色板信息,PLTEPLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成:

颜色字节意义
Red10:黑         255:红
Green10:黑         255:绿
Blue10:黑         255:蓝

注意PLTE块还必需满足以下限制条件:

1.调色板的长度应为3的倍数,即PLTE块最大字节数为256 × 3 = 768 B;

2.调色板信息的数量不能超过图像深度可以表示的范围

3.对于Colour type 3的PNG图像(索引图像),PLTE块是必需的,此时调色板的颜色索引从0开始编号,然后是1,2……;对于Colour type为2和6的图像,PLTE块是可选的,此时调色板将提供一个1—256的建议颜色集,以便软件或屏幕不支持显示真彩色时量化真彩色图像;Colour type为0和4的图像中不能出现PLTE块。

(3)IDAT

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

(4)IEND

图像结束数据IEND(image trailer chunk):它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。

值 00 00 00 00 49 45 4E 44 AE 42 60 82

2.辅助数据块

  • 透明信息数据块:tRNS chunk(Transparency chunk)
  • 图像γ数据块:gAMA(Image gamma chunk)
  • 基色和白色度数据块:cHRM(Primary chromaticities chunk)
  • 标准RGB色彩空间数据块:sRGB(Standard RGB colour space chunk)
  • 文本信息数据块:tEXt(Textual data chunk)
  • 压缩文本数据块:zTXt Compressed textual data chunk)
  • 背景颜色数据块:bKGD(Background colour chunk)
  • 物理像素尺寸数据块:pHYs(Physical pixel dimensions chunk)
  • 样本有效位数据块:sBIT(Significant bits chunk)
  • 图像直方图数据块:hIST(Palette histogram chunk)
  • 图像最后修改时间数据块:tIME(Image last-modification time chunk)

 以下详细分析其中几个:   

  1. sRGB

    使用sRGB进行颜色识别和颜色管理。如果存在sRGB块,则图像样本符合sRGB色彩空间[IEC 61966-2-1]。

    sRGB的Chunk Type Code为:115 82 71 66

    sRGB的Chunk data由一个字节组成:

    名称字节数说明
    Rendering intent10:Perceptual 适用于喜欢以输出色域为佳,而以色度精度为代价的图像,例如照片。
    1:Relative colorimetric 用于需要颜色外观匹配(相对于输出设备白点)的图像,例如徽标。
    2:Saturation 适用于希望保留饱和度但以色相和亮度为代价的图像,例如图表和图形。
    3:Absolute colorimetric 用于需要保留绝对色度的图像,例如用于其他输出设备的图像预览(校样)。
  2. gAMA,cHEM

    通常在sRGB之后写入gAMA块(以及可选的cHRM块),以便与不使用sRGB块的PNG解码器兼容。当sRGB块存在时,标准建议能对其识别并进行颜色管理的解码器忽略gAMA和cHRM块,而改用sRGB块。

    gAMA块和cHRM块的Chunk data部分:

                     gAMA
    Gamma45455
                      cHRM                 
    White point x31270
    White point y32900
    Red x64000
    Red y33000

    Green x

    30000
    Green y60000
    Blue x15000
    Blue y6000
  3. pHYs

    此数据块可表示物理分辨率

Chunk Type Code为:112 72 89 115

pHYs块的Chunk data由三部分构成:

名称字节数说明
Pixeis per unit,X axis4 
Pixeis per unit,Y axis4 
Unit specifier1

0:  单位未知

1:单位为米 

实例解析

 以下面这张V.png为例

 PNG文件标志

 文件头数据块IHDR

Length: 00 00 00 0D,与IHDRIHDR IHDRIHDR的13字节对应

Chunk Type Code: 49 48 44 52(ASCII码“IHDR”),标识该块类型

Chunk data部分:

Width:0x00 00 05 DD

Height:0x00 00 04 E5

Bit depth:8,表示8 bit深度

Colour type:6,带α通道数据的真彩色图像

Compression method:0

Filter method:0

Interlace method:0,非隔行扫描

CRC:0x52 F5 7A 8E

图像结束数据块IEND

 sRGB数据块

 Length:00 00 00 01 符合sRGB数据块标准

Chunk Type Code:73 52 47 42 标志sRGB数据块

Rendering intent:00 ,适用于喜欢以输出色域为佳,而以色度精度为代价的图像,例如照片。

CRC:AE CE 1C E9 循环冗余校验码

 gAMA数据块

 

 Length:00 00 00 04 符合gAMA数据块标准

Chunk Type Code:67 41 4D 41 标志gAMA数据块

data:00 00 B1 8F

CRC:0B FC 61 05 循环冗余校验码

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的Python代码示例,用于解析PNG文件中的tEXt块: ```python import struct def parse_text_chunk(chunk_data): null_pos = chunk_data.find(b'\0') keyword = chunk_data[:null_pos] text = chunk_data[null_pos+1:].decode('iso-8859-1') return keyword, text with open('example.png', 'rb') as f: # 读取PNG文件头 header = f.read(8) if header[:4] != b'\x89PNG': raise ValueError('File is not a PNG image') if header[4:8] != b'\r\n\x1a\n': raise ValueError('File does not have correct PNG signature') # 读取IHDR块 ihdr_length_data = f.read(4) ihdr_length = struct.unpack('!I', ihdr_length_data)[0] ihdr_type = f.read(4) if ihdr_type != b'IHDR': raise ValueError('File does not contain IHDR chunk') ihdr_data = f.read(ihdr_length) # 解析IHDR块中的数据,做相应的处理 # 读取后续块,查找tEXt块 while True: chunk_length_data = f.read(4) chunk_length = struct.unpack('!I', chunk_length_data)[0] chunk_type = f.read(4) if chunk_type == b'tEXt': chunk_data = f.read(chunk_length) keyword, text = parse_text_chunk(chunk_data) # 对tEXt块中的文本数据进行处理 elif chunk_type == b'IEND': # PNG文件读取结束 break else: # 未知块类型,跳过 f.read(chunk_length + 4) # 包括CRC校验码 ``` 上述代码中,`parse_text_chunk`函数用于解析tEXt块中的关键字和文本数据。在主函数中,先读取PNG文件头,然后逐一读取每个块,查找tEXt块并解析其中的数据。注意,PNG文件中的每个数据块都包括长度、类型、数据和CRC校验码,需要逐一读取并校验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值