PNG 格式
Portable Network Graphics
基于 chunk 的结构
PNG 大概是最干净利落的文件格式之一。所有内容都被组织成一个个“chunk”, 每个 chunk 自成一体,带着类型、数据和校验和。妙就妙在解码器可以直接跳过 自己看不懂的 chunk,PNG 因此能支持元数据,又不会让老软件读不了。
更聪明的是 chunk 的命名规则:首字母大写表示“关键”(缺了它图片就显示不出来), 小写则表示“辅助”,有更好,没有也不影响。我们关心的那些元数据 chunk 全都是辅助型的, 所以可以放心删掉。
PNG 文件结构
PNG 签名和 IHDR
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 89504E470D0A1A0A0000000D49484452 | .PNG........IHDR | |||||||||||||||
| 0010 | 00000100000001000802000000000000 | ............. | |||||||||||||||
chunk 的结构
chunk 类型的命名约定
- • 首字母大写 = 关键 chunk(必须能被理解)
- • 首字母小写 = 辅助 chunk(可选,可以忽略)
- • 第二个字母 = 公有(大写)或私有(小写)
关键 chunk
这些 chunk 必须存在、必须能被理解,图片才算有效。PicScrub 永远会保留关键 chunk。
IHDR:图像头
紧跟在签名之后的第一个 chunk,包含宽度、高度、位深、颜色类型、 压缩方法、过滤方法和隔行扫描方法,数据部分正好 13 字节。
IDAT:图像数据
存放压缩后(zlib/deflate)的图像数据,可能被拆成多个 IDAT chunk, 但所有 IDAT chunk 必须连续排列。
IEND:图像结束
标记 PNG 数据流的结束,必须是最后一个 chunk,数据部分为零字节。
PLTE:调色板
索引颜色图片(颜色类型 3)必需,包含 1–256 个 RGB 调色板条目。
元数据 chunk
这些辅助 chunk 可能装着涉及隐私的元数据,也正是 PicScrub 会清除的部分。
tEXt:未压缩文本
以 Latin-1 编码存放的键值对。常见的键有 Author、Description、 Copyright、Creation Time、Software。
zTXt:压缩文本
和 tEXt 一样,只是用 zlib 压缩过,适合放较长的文本内容。
iTXt:国际化文本
UTF-8 文本,可选压缩,支持语言标签和翻译过的关键词,XMP 元数据就放在这里。
XML:com.adobe.xmp\0eXIf:EXIF 数据
2017 年被登记为 PNG 的扩展。里面是 TIFF 格式的原始 EXIF 数据, 结构和 JPEG 里的 EXIF 一样。 可能包含 GPS、时间戳和设备信息。
iCCP:ICC 色彩配置文件
内嵌的 ICC 色彩配置文件,用 zlib 压缩。为了颜色准确,PicScrub 默认会保留它。
tIME:最后修改时间
七个字节:年(2 字节)、月、日、时、分、秒,会暴露图片最后一次被修改的时间。
与颜色相关的 chunk
这些 chunk 会影响颜色的呈现,但通常不含个人信息,PicScrub 默认保留它们。
sRGB
声明使用 sRGB 色彩空间,用一个字节表示渲染意图。
gAMA
伽马值,以 4 字节无符号整数表示(乘以 100,000 后存储)。
cHRM
三原色的色度坐标和白点坐标。
sBIT
各通道原始采样的位深。
CRC32 校验
每个 PNG chunk 都带着一个 CRC32 校验和,覆盖 chunk 类型和数据,用来保证数据完整。
CRC 的计算方式
CRC32 input = chunk_type (4 bytes) + chunk_data (N bytes) CRC32 output = 4 bytes appended after chunk data // PNG 使用的 CRC-32 多项式:0xEDB88320
PicScrub 为什么要校验 CRC
读取 PNG 文件时,PicScrub 会校验每个 chunk 的 CRC,以确保数据完整。 遇到损坏的 chunk 也会妥善处理,不会直接崩掉。
PicScrub 如何处理 PNG
校验签名
确认 PNG 签名:89 50 4E 47 0D 0A 1A 0A
解析 chunk
读取每个 chunk 的长度和类型,并校验 CRC
过滤元数据 chunk
识别并跳过 tEXt、zTXt、iTXt、eXIf、tIME 这些 chunk
重新拼出文件
写入签名 + 过滤后的 chunk + IEND
保留的 chunk
- • IHDR、PLTE、IDAT、IEND(关键)
- • sRGB、gAMA、cHRM(颜色)
- • iCCP(色彩配置文件,可选)
- • pHYs(像素尺寸)
- • tRNS(透明度)
清除的 chunk
- • tEXt(文本元数据)
- • zTXt(压缩文本)
- • iTXt(国际化文本、XMP)
- • eXIf(EXIF 数据)
- • tIME(修改时间)