便携式网络图形(PNG)规范(第三版)

W3C 推荐标准

关于此文档的更多细节
此版本
https://w3org.cn/TR/2025/REC-png-3-20250624/
最新发布版本
https://w3org.cn/TR/png-3/
最新编辑草案
https://w3c.github.io/png/
历史
https://w3org.cn/standards/history/png-3/
提交历史
实现报告
https://w3c.github.io/png/Implementation_Report_3e/
编辑
Chris Blume (W3C 特邀专家)
(MovieLabs)
Chris Lilley (W3C)
Chris Needham
Leonard Rosenthol (Adobe Inc.)
Chris Arley Seeger (NBCUniversal, LLC (Comcast Corporation 子公司))
Simon Thompson (英国广播公司 (BBC))
Cosmin Truta (W3C 特邀专家)
前任编辑
Thomas Boutell
Adam M. Costello
David Duce
Tom Lane
Glenn Randers-Pehrson
作者
Mark Adler
Thomas Boutell
Christian Brunschen
Adam M. Costello
Lee Daniel Crocker
Andreas Dilger
Oliver Fromme
Jean-loup Gailly
Phil Harvey
Chris Herborth
Alex Jakulin
Neal Kettler
Tom Lane
Alexander Lehmann
Chris Lilley (W3C)
Dave Martindale
Owen Mortensen
Stuart Parmenter
Keith S. Pickens
Robert P. Poole
Glenn Randers-Pehrson
Greg Roelofs
Willem van Schaik
Guy Schalnat
Paul Schmidt
Andrew Smith
Michael Stokes
Vladimir Vukicevic
Tim Wegner
Jeremy Wohl
反馈
GitHub w3c/png (合并请求, 新建问题, 开放问题)
public-png@w3.org,邮件主题请使用 [png-3] …讨论主题… (邮件归档)
勘误表
https://w3org.cn/2025/06/REC-PNG-20250624-errata

另见 译本


摘要

本文件描述了 PNG(便携式网络图形),这是一种用于无损、便携、高压缩存储静态和动画光栅图像的可扩展文件格式。PNG 为 GIF 提供了免专利替代方案,并可替代 TIFF 的许多常见用途。它支持索引色灰度真彩色图像,并可选择添加 Alpha 通道。采样深度范围为 1 到 16 位。

PNG 设计旨在良好适用于在线浏览应用程序(如万维网),因此它具有完全的可流式传输性,并包含渐进式显示选项。PNG 非常稳健,提供完整的文件完整性检查和简单常见的传输错误检测。此外,PNG 可以存储色彩空间数据,以改善在异构平台上的色彩匹配效果。

本规范定义了两种互联网媒体类型:image/png 和 image/apng。

本文档状态

本节描述了本文档发布时的状态。当前的 W3C 出版物列表及本技术报告的最新修订版可在 W3C 标准与草案索引(网址:https://w3org.cn/TR/)中找到。

本规范旨在成为一项国际标准,但目前尚未达成。将本规范称为“国际标准”是不恰当的。

本文件由 便携式网络图形 (PNG) 工作组 作为推荐标准发布,遵循 推荐标准轨道

W3C 推荐标准是一项经由广泛共识,由 W3C 及其成员背书,且工作组成员承诺为其实施提供免版税许可的规范。

W3C 建议将本规范广泛部署为 Web 标准。

本文件由遵循 W3C 专利政策 的工作组制作。W3C 维护着一份 与该工作组交付成果相关的专利披露公开列表;该页面还包含专利披露的说明。任何拥有专利实际知识且认为该专利包含 必要权利要求 (Essential Claim) 的个人,必须根据 W3C 专利政策第 6 节披露相关信息。

本文档受 2023 年 11 月 3 日 W3C 流程文档 管辖。

1. 简介

本规范的设计目标是:

  1. 可移植性:编码、解码和传输应与软件和硬件平台无关。
  2. 完整性:应能表示真彩色索引色灰度图像,每种情况均可选择透明度、色彩空间信息以及文本注释等辅助信息。
  3. 串行编码和解码:数据流应能被串行生成和串行读取,允许数据流格式用于在串行通信通道上进行即时生成和显示图像。
  4. 渐进式呈现:应能以这样一种方式传输数据流,即在接收初期呈现整个图像的近似概貌,并随着数据流的接收逐步增强图像质量。
  5. 传输错误的稳健性:应能可靠地检测数据流传输错误。
  6. 无损性:过滤和压缩应保留所有信息。
  7. 性能:任何过滤、压缩和渐进式图像呈现都应旨在高效解码和呈现。快速编码的目标比快速解码次要。解码速度可以以牺牲编码速度为代价来实现。
  8. 压缩:图像应在与其他设计目标一致的前提下实现有效压缩。
  9. 简洁性:开发者应能轻松实现该标准。
  10. 互操作性:任何符合标准的 PNG 解码器都必须能够读取所有符合标准的 PNG 数据流。
  11. 灵活性:在不损害标准 PNG 数据流互操作性的前提下,应允许未来的扩展和私有添加。
  12. 无法律限制:不应使用非免费提供的算法。

2. 范围

本规范规定了一种数据流及其相关文件格式——便携式网络图形(PNG,发音为“ping”),用于通过互联网传输无损、便携、压缩的个人计算机图形图像或基于帧的动画。

3. 术语、定义和缩略语

就本规范而言,适用以下定义。

byte
octet
范围在 [0, 255] 内的 8 位二进制整数,其中最高有效位为第 7 位,最低有效位为第 0 位。
字节序 (Byte order)
多字节数据值的字节排列顺序。
色度 (Chromaticity)
在 [COLORIMETRY] 中指定的 xyY 空间中的 xy 值对。

色度是衡量颜色质量的指标,与其亮度无关。

合成 (Composite, 动词)
通过合并前景图像和背景图像来形成图像,使用透明度信息来确定背景在何处以及在何种程度上可见。

前景图像被称为相对于背景进行了合成

数据流 (Datastream)
字节序列。
DEFLATE
LZ77 压缩方法系列中的一员。

来源:[RFC1951]

frame
对于静态 PNG,静态图像被视为第一帧(也是唯一一帧)。对于动画 PNG,构成基于帧的动画序列的每一张图像都是一帧。因此,对于动画 PNG,当静态图像不是第一帧时,该静态图像不被视为一帧。
帧缓冲区 (Frame buffer)
大多数类型的计算机显示器所展示图像的最终数字存储区域。

软件通过将图像加载到帧缓冲区中,使图像出现在屏幕上。

完全透明的黑色 (Fully transparent black)
红、绿、蓝和 Alpha 分量均为零的像素。
伽马值 (Gamma value)
伽马转换函数的指数值。
伽马函数 (gamma)
幂律转换函数
高动态范围 (HDR)
一种能够存储具有相对高动态范围图像的图像格式,该范围类似于或超过人类视觉系统的瞬时动态范围(~12-14 )。PNG 允许使用两种 HDR 格式:HLGPQ [ITU-R-BT.2100]。
混合对数伽马 (HLG)
[ITU-R-BT.2100] 表 5 中定义的转换函数。(一种相对场景参考系统。)
全范围图像 (Full-range image)
参考黑和参考白分别对应采样值 02位深 - 1 的图像。
图像数据 (Image data)
图像内的一维扫描线数组。
隔行扫描 PNG 图像 (Interlaced PNG image)
通过通道提取PNG 图像生成的缩减图像序列。
无损 (Lossless)
一种允许精确、逐位重建原始数据的数据压缩方法。
亮度 (Luminance)
对可见光强度的客观测量,考虑到人眼对不同波长的敏感度。

亮度和色度共同完整定义了测量出的颜色。有关正式定义,请参阅 [COLORIMETRY]。

LZ77
[Ziv-Lempel] 中描述的数据压缩算法。
窄范围图像 (Narrow-range image)
参考黑和参考白不分别对应采样值 02位深 - 1 的图像。
网络字节序 (Network byte order)
一种字节序,其中最高有效字节优先,随后是重要性递减的字节(双字节整数为 MSB LSB,四字节整数为 MSB B2 B1 LSB)。
感知量化器 (PQ)
[ITU-R-BT.2100] 表 4 中定义的转换函数。(一种绝对显示参考系统。)

PNG 中仅可使用 RGB,不支持 ICtCp。

PNG 解码器 (PNG decoder)
PNG 数据流重建参考图像并生成相应输出图像的过程或设备。
PNG 编辑器 (PNG editor)
创建对现有 PNG 数据流进行修改的过程或设备,尽可能保留未修改的辅助信息,并遵守数据块排序规则(即使对于未知数据块类型亦是如此)。
PNG 编码器 (PNG encoder)
源图像构建参考图像,并生成表示该参考图像的 PNG 数据流的过程或设备。
PNG 文件 (PNG file)
作为文件存储的 PNG 数据流
PNG 四字节无符号整数

限制在 0 到 231-1 范围内的四字节无符号整数。

实施此限制是为了适配那些处理无符号四字节值有困难的编程语言。

PNG 双字节无符号整数

网络字节序下的双字节无符号整数。

sample (采样)
图像中通道像素的交集。
采样深度 (Sample depth)
用于表示采样值的位数。
扫描线 (Scanline)
图像或隔行扫描 PNG 图像中的像素行。
标准动态范围 (SDR)
一种能够存储具有 5-8 相对低动态范围图像的图像格式。示例包括 [SRGB]、[Display-P3]、[ITU-R-BT.709]。

标准动态范围与原色无关,因此也与色域无关。PNG 支持宽色域 SDR 格式。

stop
场景光亮度变化 2 倍。
转换函数 (Transfer function)
关联图像亮度和图像采样的函数。
白点 (White point)
计算机显示器标称白值的色度
zlib

DEFLATE 风格的压缩方法。

来源:[rfc1950]

也指包含此方法示例实现的库的名称。

循环冗余校验 (Cyclic Redundancy Code)
CRC

一种旨在检测大多数传输错误的校验值类型。

解码器计算接收数据的 CRC,并通过将其与编码器计算并附加到数据上的 CRC 进行比较来进行校验。不匹配表示数据或 CRC 在传输过程中已损坏。

阴极射线管 (Cathode Ray Tube)
CRT
包含一个或多个电子枪的真空管,通过操作发射电子束在荧光屏上显示图像。
电光转换函数 (Electro-Optical Transfer Function)
EOTF
电气或数字域与光能之间的转换函数。它定义了显示器针对给定输入信号发出的光量。
最低有效字节 (Least Significant Byte)
LSB
字节值的最低有效字节。
最高有效字节 (Most Significant Byte)
MSB
字节值的最高有效字节。
光电转换函数 (Opto-Electrical Transfer Function)
OETF
光能与电气或数字域之间的转换函数。它定义了产生给定输出信号所需的场景光量。

4. 概念

4.1 静态和动画图像

所有 PNG 图像都包含单个静态图像

某些 PNG 图像——称为动画 PNG (APNG)——还包含基于帧的动画序列,即动画图像。动画的第一帧可以是(但不一定是)静态图像。不支持动画的显示设备(如打印机)将显示静态图像,而不是动画序列。

静态图像以及动画图像的每一帧都对应一个参考图像,并作为PNG 图像进行存储。

4.2 图像

本规范指定了 PNG 数据流,并对生成 PNG 数据流的 PNG 编码器、解释 PNG 数据流的 PNG 解码器,以及将一个 PNG 数据流转换为另一个的 PNG 编辑器提出了一些要求。它没有指定应用程序与 PNG 编码器、解码器或编辑器之间的接口。图像呈现给编码器或由解码器输出的具体形式未作规定。区分了四种图像。

源图像 (Source image)
源图像是呈现给 PNG 编码器的图像。
参考图像 (Reference image)
仅在概念上存在的参考图像是一个矩形像素阵列(像素也是矩形的),所有像素具有相同的宽度和高度,并包含相同数量的无符号整数采样,即三个(红、绿、蓝)或四个(红、绿、蓝、Alpha)。特定类型(红、绿、蓝或 Alpha)的所有采样的数组称为通道。每个通道的采样深度在 1 到 16 之间,这是通道中每个采样使用的位数。不同通道可能具有不同的采样深度。红、绿、蓝采样决定了像素颜色的红、绿、蓝分量的强度;如果它们全部为零,像素为黑色,如果它们全部达到最大值 (2采样深度-1),则像素为白色。Alpha 采样决定像素的不透明度,零表示完全透明,最大值表示完全不透明。在三通道参考图像中,所有像素完全不透明。(四通道参考图像也可以所有像素完全不透明;区别在于后者具有特定的 Alpha 采样深度,而前者没有。)每个水平像素行称为扫描线。像素在每条扫描线内从左到右排序,扫描线从上到下排序。每个参考图像都可以精确表示为 PNG 数据流,每个 PNG 数据流都可以转换为参考图像。PNG 编码器可以直接将源图像转换为 PNG 图像,但在概念上,它首先将源图像转换为参考图像,然后将参考图像转换为 PNG 图像。根据源图像的类型,从源图像到参考图像的转换可能会导致信息丢失。该转换不在本国际标准的范围内。然而,参考图像总是可以从 PNG 数据流中精确恢复。
PNG 图像 (PNG image)
PNG 图像是通过一系列转换从参考图像获得的:Alpha 分离索引化RGB 合并Alpha 压缩采样深度缩放。定义了五种 PNG 图像类型(见 6.1 颜色类型和值)。(如果 PNG 编码器直接将源图像转换为 PNG 图像,并且源图像格式已经类似于 PNG 图像格式,编码器可能能够避免进行某些转换。)尽管 PNG 图像中并未显式支持 1 到 16 位之间的所有采样深度,但参考图像每个通道中的有效位数可以被记录下来。PNG 图像中的所有通道具有相同的采样深度。PNG 编码器从 PNG 图像生成 PNG 数据流。PNG 解码器获取 PNG 数据流并重新创建 PNG 图像。
输出图像 (Delivered image)
输出图像是由解码 PNG 数据流后获得的 PNG 图像构建的。未为输出图像指定特定格式。查看器会向用户呈现尽可能接近原始源图像外观的图像。

这四种图像之间的关系如图 1 所示。

1 源、参考、PNG 和显示图像之间的关系

采样、通道、像素和采样深度之间的关系如图 2 所示。

2 采样、采样深度、像素和通道之间的关系

4.3 色彩空间

颜色采样所在的 RGB 色彩空间可以通过以下四种方式之一指定:

  1. 通过 CICP 图像格式信令元数据;
  2. 通过 ICC 配置文件;
  3. 当采样符合 sRGB 色彩空间时,明确指定色彩空间为 sRGB;
  4. 通过指定伽马值以及图像中使用的红、绿、蓝原色和参考白点的 1931 CIE x,y 色度。

对于高端应用,前两种方法提供了最大的灵活性和控制力。第三种方法能够指示一种特定但极其常见的色彩空间。第四种方法在 ICC 配置文件被广泛采用之前就已标准化,它允许指定 RGB 数据的精确色度,以及要应用的伽马校正(见 C. 伽马和色度)。然而,色彩感知应用程序会倾向于前三种方法中的一种,而色彩无感知应用程序通常会忽略所有四种方法。

1 是提供色彩空间信息的数据块类型列表,每个数据块都关联有一个优先级数字。如果单个图像包含不止一种这些数据块类型,则优先级数字最小的数据块应优先,更高数字的数据块类型应被忽略。

1 颜色数据块优先级
数据块类型 优先级
cICP 1
iCCP 2
sRGB 3
cHRMgAMA 4

伽马校正不应用于 Alpha 通道(如果存在)。Alpha 采样始终为全范围,表示完全不透明度的线性分数。

还可以提供母版制作元数据。

4.4 参考图像到 PNG 图像的转换

引言

参考图像在被编码为 PNG 图像前,需进行若干转换(见 3)。转换按以下顺序应用,方括号表示该转换是可选的:

[alpha separation]
indexing or ( [RGB merging] [alpha compaction] )
sample depth scaling

当每个像素要么完全透明要么完全不透明时,Alpha 分离Alpha 压缩索引化转换可能导致恢复的参考图像具有与原始参考图像不同的 Alpha 采样深度,或者完全没有 Alpha 通道。这对任何像素的不透明度都没有影响。这两个参考图像被视为等效,转换被视为无损。尽管如此,希望保留 Alpha 采样深度的编码器可以选择不执行会改变 Alpha 采样深度的转换。

3 参考图像到 PNG 图像的转换

4.4.1 Alpha 分离

如果参考图像中的所有 Alpha 采样都具有最大值,则可以省略 Alpha 通道,从而得到一个可以更紧凑编码的等效图像。

4.4.2 索引化

如果不同像素值的数量为 256 或更少,RGB 采样深度不大于 8,且 Alpha 通道缺失、恰好为 8 位深,或者每个像素要么完全透明要么完全不透明,那么通过索引化转换实现的替代索引色表示在编码时可能更有效。在索引色表示中,每个像素被替换为调色板的索引。调色板是包含三个 8 位采样(红、绿、蓝)的条目列表。如果存在 Alpha 通道,则还有一个平行的 8 位 Alpha 采样表,称为Alpha 表

4 索引色图像

即使 PNG 图像不是索引色,也可以构建一个或多个建议调色板,以辅助只能显示有限数量颜色的查看器。

对于索引色图像,编码器可以重新排列调色板,使得具有最大 Alpha 值的表条目被分组在末尾。在这种情况下,表可以以不包含这些条目的缩短形式进行编码。

创建索引色 PNG 的编码器不得插入大于调色板表实际长度的索引值;这样做是错误的,解码器对该错误的处理方式各不相同。

4.4.3 RGB 合并

如果红、绿、蓝通道具有相同的采样深度,并且对于每个像素,红、绿、蓝采样值相等,则这三个通道可以合并为单个灰度通道。

4.4.4 Alpha 压缩

对于非索引图像,如果存在某种 RGB(或灰度)值,使得所有具有该值的像素都是完全透明的,而所有其他像素都是完全不透明的,则可以通过仅识别该透明的 RGB(或灰度)值来更紧凑地表示 Alpha 通道。

4.4.5 采样深度缩放

在 PNG 图像中,并非支持所有采样深度(见 6.1 颜色类型和值),且所有通道必须具有相同的采样深度。PNG 图像的所有通道使用不小于参考图像中任何采样深度的最小允许采样深度,参考图像中的可能采样值被线性映射到 PNG 图像的下一个允许范围内。5 展示了深度为 3 的采样如何映射到深度为 4 的采样。

5 缩放采样值

仅允许少量采样深度减少了解码器需要处理的情况。采样深度缩放是可逆且无数据丢失的,因为参考图像采样深度可以记录在 PNG 数据流中。在没有记录采样深度的情况下,参考图像采样深度等于 PNG 图像采样深度。见 12.4 采样深度缩放13.12 采样深度重新缩放

6 可能的 PNG 图像像素类型

4.5 PNG 图像

参考图像的转换产生五种 PNG 图像类型之一(见 6):

带 Alpha 的真彩色
每个像素由四个采样组成:红、绿、蓝和Alpha
带 Alpha 的灰度
每个像素由两个采样组成:一个灰度采样和一个Alpha采样。
真彩色
每个像素由三个采样三元组组成:红、绿、蓝。可选的 Alpha 通道可以指定为单个红、绿、蓝采样三元组:图像中红、绿、蓝采样与 Alpha 通道的红、绿、蓝采样相同的像素是完全透明的;其他像素是完全不透明的。如果没有 Alpha 通道,所有像素都是完全不透明的。
灰度
每个像素由单个灰度采样组成,代表整体亮度(从黑到白的量表)。可选的 Alpha 通道可以指定为单个灰度采样:图像中灰度采样与 Alpha 通道的灰度采样相同的像素是完全透明的;其他像素是完全不透明的。如果没有 Alpha 通道,所有像素都是完全不透明的。
索引色
每个像素由指向调色板(以及关联的 Alpha 值表,如果存在)的索引组成。

每个像素的格式取决于 PNG 图像类型和位深。对于除索引色以外的 PNG 图像类型,位深指定每个采样的位数,而不是每个像素的总位数。对于索引色图像,位深指定每个调色板索引的位数,而不是调色板或 Alpha 表中颜色的采样深度。像素内的采样顺序如下(取决于 PNG 图像类型):

  1. 带 Alpha 的真彩色:红、绿、蓝、Alpha。
  2. 带 Alpha 的灰度:灰度、Alpha。
  3. 真彩色:红、绿、蓝。
  4. 灰度:灰度。
  5. 索引色:调色板索引。

4.6 编码 PNG 图像

引言

PNG 图像编码过程的概念模型如图 7 所示。这些步骤指的是对 PNG 图像中像素数组或索引数组的操作。调色板Alpha 表不以这种方式编码。

  1. 通道提取:为支持渐进式显示,PNG 图像像素可以重新排列以形成几个较小的图像,称为缩减图像或通道。
  2. 扫描线序列化:图像按扫描线进行序列化。像素在扫描线中从左到右排序,扫描线从上到下排序。
  3. 过滤:每条扫描线使用定义的过滤类型之一转换为过滤后的扫描线,为图像压缩做好准备。
  4. 压缩:对图像中所有过滤后的扫描线进行压缩。
  5. 分块:压缩后的图像被划分为大小方便的数据块。为每个数据块添加错误检测码。
  6. 数据流构建:将数据块插入数据流。

4.6.1 通道提取

通道提取(见 7)将 PNG 图像拆分为一系列缩减图像,其中第一个图像定义粗略视图,后续图像增强该粗略视图,直到最后一个图像完成 PNG 图像。缩减图像集也称为隔行扫描 PNG 图像。本规范定义了两种隔行扫描方法。第一种方法为空方法;像素按顺序从左到右存储,扫描线从上到下存储。第二种方法对图像进行多次扫描,以产生七个缩减图像序列。示例图像的七个通道如图 7 所示。见 8. 隔行扫描和通道提取

7 编码 PNG 图像
8 通道提取

4.6.2 扫描线序列化

每一行像素(称为扫描线)表示为字节序列。

4.6.3 过滤

PNG 允许图像数据在压缩前进行过滤。过滤可以提高数据的压缩性。过滤操作是确定性的、可逆的和无损的。这使得解压后的数据可以进行反向过滤,以获取原始数据。见 7.3 过滤

4.6.4 压缩

PNG 图像通道中的过滤扫描线序列通过定义的一种压缩方法进行压缩(见 9)。连接后的过滤扫描线构成压缩阶段的输入。压缩阶段的输出是单个压缩数据流。见 10. 压缩

4.6.5 分块

分块提供了将压缩数据流分解为易于管理的数据块的方法(见 9)。每个数据块都有自己的冗余校验。见 11. 数据块规范

9 压缩和分块

4.7 附加信息

辅助信息可能与图像关联。解码器可以忽略全部或部分辅助信息。所提供的辅助信息类型在 2 中描述。

2 辅助信息类型
信息类型 描述
动画信息 一个动画图像,定义为一系列具有关联时间、位置和处理信息的帧,如果查看器具备相应能力,则应显示该动画。对于其他情况(如打印机),将显示静态图像
背景色 如果无法获得更好的选择,则在呈现图像时使用的纯色背景色。
编码独立码点 通过枚举元数据(如转换函数和色度原色)来标识色彩空间。最初用于 SDRHDR 视频,也用于静态和动画图像。
内容光照水平信息 图像(或图像序列)中最亮像素的亮度以及序列中最亮帧的平均亮度水平。
EXIF 信息 可交换图像文件格式元数据,如快门速度、光圈和方向。
伽马和色度 相对于所需输出强度的图像伽马值,以及图像中使用的 RGB 值的色度特性。
ICC 配置文件 图像中采样所符合的色彩空间描述(以国际色彩联盟 (ICC) 配置文件的形式)。
图像直方图 图像使用每个调色板条目的频率估计。
母版显示色彩体积 描述用于制作内容显示器的绝对三维色域体积,包括母版显示器可以再现的最亮和最暗颜色。这有助于在显示设备上呈现图像。
物理像素尺寸 呈现 PNG 图像时应使用的目标像素尺寸和纵横比。
有效位 采样中具有意义的位数。
sRGB 色彩空间 一种渲染意图(由国际色彩联盟定义)以及图像采样符合该色彩空间的指示。
建议调色板 当显示设备无法显示图像中的全部颜色范围时,可以使用的缩减调色板。
文本数据 与图像关联的(可能经过压缩的)文本信息。
时间 PNG 图像最后一次修改的时间。
透明度 允许在 PNG 图像中未保留 Alpha 通道时重建参考图像的 Alpha 信息。

4.8 PNG 数据流

4.8.1 数据块 (Chunks)

PNG 数据流由 PNG 签名(见 5.2 PNG 签名)后跟一系列数据块(见 11. 数据块规范)组成。每个数据块都有一个指定其功能的数据块类型。

4.8.2 数据块类型

数据块类型是四字节序列,选择这些序列是为了使其在根据 ISO 646.IRV:1991 [ISO646] 字符集解释时对应于可读标签。前四个称为关键数据块,必须根据本规范的规定进行理解和正确解释。它们是:

  1. IHDR:图像头,是 PNG 数据流中的第一个数据块。
  2. PLTE:与索引 PNG 图像关联的调色板表。
  3. IDAT:图像数据数据块。
  4. IEND:图像结尾,是 PNG 数据流中的最后一个数据块。

其余数据块类型称为辅助数据块类型,编码器可以生成,解码器可以选择性解释。

  1. 透明度信息:tRNS(见 11.3.1 透明度信息)。
  2. 色彩空间信息:cHRM, gAMA, iCCP, sBIT, sRGB, cICP, mDCV(见 11.3.2 色彩空间信息)。
  3. 文本信息:iTXt, tEXt, zTXt(见 11.3.3 文本信息)。
  4. 杂项信息:bKGD, hIST, pHYs, sPLT, eXIf(见 11.3.4 杂项信息)。
  5. 时间信息:tIME(见 11.3.5 时间戳信息)。
  6. 动画信息:acTL, fcTL, fdAT(见 11.3.6 动画信息)。

4.9 APNG:基于帧的动画

引言

动画 PNG (APNG) 扩展了原始的静态 PNG 格式,增加了对基于帧动画图像的支持。它旨在替代传统上使用 GIF 格式 [GIF] 的简单动画图像,同时增加了对 GIF 所缺乏的 24 位图像和 8 位透明度的支持。

APNG 向后兼容 PNG 的早期版本;非动画 PNG 解码器将忽略辅助性的 APNG 专用数据块,并显示静态图像

4.9.1 结构

APNG 流是 PNG 规范先前版本中定义的普通 PNG 流,并增加了三个额外的数据块类型,用于描述动画并提供额外的帧数据。

要被识别为 APNGacTL 数据块必须出现在流中任何 IDAT 数据块之前。acTL 结构如下所述

概念上,在每次播放开始时,输出缓冲区应完全初始化为一个完全透明的黑色矩形,其宽度和高度尺寸来自 IHDR 数据块。

静态图像可以通过在 IDAT 之前存在单个 fcTL 数据块而被包含为动画的第一帧。否则,静态图像不是动画的一部分。

随后的帧在 fdAT 数据块中编码,其结构与 IDAT 数据块相同,只是前面加上了一个序列号。每帧有关放置和渲染的信息存储在 fcTL 数据块中。fdATfcTL 数据块的完整布局如下所述

整个动画的边界由 IHDR 数据块的宽度和高度参数指定,无论默认图像是否是动画的一部分。如果后续帧需要额外空间,则默认图像应适当地填充完全透明的黑色像素。

每一帧在每次播放时都是相同的,因此应用程序缓存这些帧是安全的。

4.9.2 序列号

fcTLfdAT 数据块具有从零开始的 4 字节序列号。这两种数据块类型共享该序列。此数字的目的是检测(并可选择纠正)动画 PNG 中的序列错误,因为本规范不对辅助数据块施加排序限制。

第一个 fcTL 数据块应包含序列号 0,其余 fcTLfdAT 数据块中的序列号应按升序排列,没有间隙或重复。

下表说明了图像具有不止一帧,以及第二帧具有不止一个 fdAT 数据块时序列号的使用。(为清晰起见,省略了表中的 IHDRIEND 数据块)。

3 如果静态图像也是第一帧
序列号 数据块
(none) acTL
0 fcTL 第一帧
(none) IDAT 第一帧 / 静态图像
1 fcTL 第二帧
2 第二帧的第一个 fdAT
3 第二帧的第二个 fdAT
4 如果静态图像不是动画的一部分
序列号 数据块
(none) acTL
(none) IDAT 静态图像
0 fcTL 第一帧
1 第一帧的第一个 fdAT
2 第一帧的第二个 fdAT
3 fcTL 第二帧
4 第二帧的第一个 fdAT
5 第二帧的第二个 fdAT

4.9.3 输出缓冲区

输出缓冲区是一个像素数组,其尺寸由 PNG IHDR 数据块的宽度和高度参数指定。概念上,每一帧在被合成画布之前,都会在输出缓冲区中构建。输出缓冲区的内容可供解码器使用。输出缓冲区的角映射到画布的角。

4.9.4 画布

画布是输出设备上用于显示帧的区域。画布的内容不一定对解码器可用。如果存在 bKGD 数据块,且没有更好的背景,则可以使用它来填充画布。

4.10 错误处理

PNG 数据流中的错误可分为两类:

  1. 传输错误或计算机文件系统损坏,往往会损坏大部分或全部数据流;
  2. 语法错误,表现为数据块中的无效值,或缺失或错位的数据块。语法错误不仅可能由编码错误引起,还可能由使用注册或私有值引起,如果这些值对解码器来说是未知的。

PNG 解码器应尽早检测错误,尽可能从错误中恢复,否则应优雅地失败。错误处理理念在 13.1 错误处理 中有详细描述。

4.11 扩展

本节是非规范性的。

PNG 格式提供了几个扩展点

其中一些扩展点由 W3C 保留,而另一些则可供私有使用。

5. 数据流结构

5.1 PNG 数据流

PNG 数据流 由一个 PNG 签名及其后的一系列数据块组成。它是编码 PNG 图像 的结果。

使用“数据流”这一术语而不是“文件”,是为了描述一个可能只是文件一部分的字节序列。它也用于强调字节序列可能是“动态”生成和消费的,根本不会出现在存储的文件中。

5.2 PNG 签名

PNG 数据流的前八个字节始终包含以下十六进制值


89 50 4E 47 0D 0A 1A 0A

此签名表明数据流的其余部分包含单个 PNG 图像,该图像由一系列数据块组成,以 IHDR 块开头,以 IEND 块结尾。

此签名将 PNG 数据流与其他类型的 数据流 区分开来,并允许及早发现某些传输错误。

5.3 数据块布局

每个 数据块 (chunk) 由三个或四个字段组成(参见 10)。字段的含义在 5 中进行了描述。数据块的数据字段可以为空。

10 数据块组成部分
5 数据块字段
名称 描述
长度 (Length) 一个 PNG 四字节无符号整数,给出数据块数据字段中的字节数。该长度计算数据字段,计算其自身、块类型或 CRC。零是一个有效的长度。尽管编码器和解码器应将长度视为无符号,但其值不得超过 231-1 字节。
数据块类型 定义块类型的四个字节序列。块类型的每个字节仅限于十六进制值 41 到 5A 以及 61 到 7A。这些分别对应于 ISO 646 [ISO646] 中的大写和小写字母(A-Za-z),以便于描述和检查 PNG 数据流。编码器和解码器应将块类型视为固定的二进制值,而不是字符字符串。例如,用 UCS 2 字符集中这些字母的等效项来表示块类型 IDAT 是不正确的。关于块类型的其他命名约定在 5.4 块命名约定 中讨论。
块数据 适用于块类型的相关数据字节(如果有)。 该字段可以为零长度。
CRC 一个四字节的 CRC,是对数据块中前面的字节计算得出的,包括块类型字段和块数据字段,但包括长度字段。该 CRC 可用于检查数据是否损坏。即使对于不包含数据的数据块,CRC 也始终存在。参见 5.5 CRC 算法

数据块数据长度可以是最大值以内的任意字节数;因此,实现者不能假设数据块在大于字节的任何边界上对齐。

5.4 数据块命名约定

选择块类型时,将其字节解释为 ISO 646 字母 [ISO646] 时具有意义。分配块类型是为了即使在未识别类型的情况下,解码器也能确定数据块的某些属性。这些规则通过允许 PNG 解码器在遇到未知数据块时决定如何处理,实现了 PNG 格式的安全、灵活扩展。

只有在解码器无法识别数据块类型时,命名规则通常才具有相关性,详见 13. PNG 解码器和查看器

块类型的四位属性位,即每个字节的第 5 位(值 32),用于传达数据块属性。此选择意味着人类可以根据块类型每个字节对应的字母是大写(第 5 位为 0)还是小写(第 5 位为 1)来读取分配的属性。

属性位是块类型的固有部分,因此对于任何块类型都是固定的。因此,CHNKcHNk 将是互不相关的块类型,而不是具有不同属性的相同数据块。

属性位的语义定义在 6 中。

6 属性位的语义
名称与位置 定义 描述
辅助位:第一个字节 0(大写)= 关键,
1(小写)= 辅助。
关键数据块对于成功显示数据流的内容是必要的,例如图像头数据块 (IHDR)。解码器在尝试提取图像时,如果遇到未知类型且辅助位为 0 的数据块,应向用户指示该图像包含其无法安全解释的信息。
辅助数据块对于有意义地显示数据流的内容并非绝对必要,例如时间数据块 (tIME)。解码器在遇到未知类型且辅助位为 1 的数据块时,可以安全地忽略该块并继续显示图像。
私有位:第二个字节 0(大写)= 公共,
1(小写)= 私有。
公共数据块由 W3C 保留以供定义。私有数据块的定义在 12.10.1 私有数据块的使用 中指定。私有数据块名称的第二个字母为小写,而公共数据块名称的第二个字母为大写。
保留位:第三个字节 在此版本的 PNG 中为 0(大写)。
如果保留位为 1,则数据流不符合此版本的 PNG。
块名称第三个字母的大小写的意义被保留以用于可能的未来扩展。在本国际标准中,所有块名称的第三个字母都应为大写。
可安全复制位:第四个字节 0(大写)= 不可安全复制,
1(小写)= 可安全复制。
此属性位对纯解码器而言不重要,但 PNG 编辑器 需要它。此位定义了在修改数据流时如何正确处理未识别的数据块。PNG 编辑器 的规则在 14.2 PNG 编辑器的行为 中进一步讨论。

假设的块类型 "cHNk" 具有以下属性位

cHNk  <-- 32 bit chunk type represented in text form
||||
|||+- Safe-to-copy bit is 1 (lower case letter; bit 5 is 1)
||+-- Reserved bit is 0     (upper case letter; bit 5 is 0)
|+--- Private bit is 0      (upper case letter; bit 5 is 0)
+---- Ancillary bit is 1    (lower case letter; bit 5 is 1)

因此,该名称表示一个辅助、公共、可安全复制的数据块。

5.5 CRC 算法

CRC 字段是使用带预调节和后调节的标准 CRC 方法计算的,如 [ISO-3309] 和 [ITU-T-V.42] 所定义。所采用的 CRC 多项式(与 GZIP 文件格式规范 [RFC1952] 中使用的相同)为

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

在 PNG 中,32 位 CRC 初始化为全 1,然后从最低有效位 (1) 到最高有效位 (128) 处理每个字节的数据。所有数据字节处理完毕后,CRC 将被取反(取其按位反码)。该值以 MSB 优先的顺序传输(存储在数据流中)。为了区分字节和排序,32 位 CRC 的最低有效位被定义为 x31 项的系数。

CRC 的实际计算通常采用预计算表来加速计算。参见 D. CRC 实现示例

5.6 数据块顺序

关于各个数据块定位的约束列在 7 中,并以图表形式说明:静态图像参见 1112;静态图像构成第一帧的动画图像参见 1314;静态图像不是动画一部分的动画图像参见 1516。这些网格图表示本规范施加的定位约束。图中的线条定义了偏序关系。较高的块应出现在较低的块之前。在水平对齐并位于其他两个块类型(高于和低于水平对齐的块)之间的块,可以在它们所连接的两个较高和较低块类型之间的任何顺序中出现。与块类型相关的上标定义在 8 中。它指示该数据块是强制性的、可选的,还是可以出现多次。两个块类型之间的垂直条表示替代选项。

7 数据块排序规则
关键数据块
(应按此顺序出现,PLTE 除外为可选)
块名称 允许出现多次 排序约束
IHDR No 应位于最前
PLTE No 在第一个 IDAT 之前
IDAT 多个 IDAT 块应连续
IEND No 应位于最后
辅助数据块
(无需按此顺序出现)
块名称 允许出现多次 排序约束
acTL No IDAT 之前
cHRM No PLTEIDAT 之前
cICP No PLTEIDAT 之前
gAMA No PLTEIDAT 之前
iCCP No PLTEIDAT 之前。如果存在 iCCP 块,则不应存在 sRGB 块。
mDCV No PLTEIDAT 之前。
cLLI No PLTEIDAT 之前。
sBIT No PLTEIDAT 之前
sRGB No PLTEIDAT 之前。如果存在 sRGB 块,则不应存在 iCCP 块。
bKGD No PLTE 之后;在 IDAT 之前
hIST No PLTE 之后;在 IDAT 之前
tRNS No PLTE 之后;在 IDAT 之前
eXIf No IDAT 之前
fcTL 一个可能出现在 IDAT 之前;所有其他应出现在 IDAT 之后
pHYs No IDAT 之前
sPLT IDAT 之前
fdAT IDAT 之后
tIME No
iTXt
tEXt
zTXt
8 网格图中使用的符号含义
Symbol 含义
+ 一个或多个
1 仅一个
? 零或一
* 零或多
| 替代选项
11 网格图:带有 PLTE 的静态 PNG 图像
12 网格图:没有 PLTE 的静态 PNG 图像
13 网格图:带有 PLTE 的动画 PNG 图像,静态图像构成第一帧
14 网格图:没有 PLTE 的动画 PNG 图像,静态图像构成第一帧
15 网格图:带有 PLTE 的动画 PNG 图像,静态图像不是动画的一部分
16 网格图:没有 PLTE 的动画 PNG 图像,静态图像不是动画的一部分

5.7 定义数据块

5.7.1 概览

所有私有和公共数据块 应当 (SHOULD) 在 [PNG-EXTENSIONS] 中列出。

5.7.2 定义公共数据块

公共数据块由 W3C 保留以供定义。

公共数据块旨在符合 PNG 的理念进行广泛使用。

鼓励组织和应用程序提交任何符合上述标准的数据块,由 PNG 工作组 定义为公共数据块。

作为公共数据块的定义既不是自动的也不是即时的。建议的公共数据块类型在被定义之前 不得 (SHALL NOT) 在公开可用的软件或数据流中使用。

除非必要,否则不鼓励定义新的关键数据块类型。

5.7.3 定义私有数据块

组织和应用程序 可以 (MAY) 为私有和实验性用途定义私有数据块。

私有数据块 不应该 (SHOULD NOT) 仅仅为了承载人类用户感兴趣的文本信息而定义。相反,应该 (SHOULD) 使用 iTXt 块,并定义相应的关键字。

在 [PNG-EXTENSIONS] 中列出私有数据块可以减少但不能消除不同应用程序将相同的私有数据块用于不兼容目的的可能性。如果使用私有数据块类型,则 应当 (SHOULD) 在数据块数据的开头存储额外的标识信息,以进一步降低冲突风险。

对于所有存储对于查看图像非绝对必要的信息的私有数据块,应当 (SHOULD) 使用辅助数据块类型,而不是关键数据块类型。

不应该 (SHOULD NOT) 定义私有关键数据块,因为包含此类数据块的 PNG 数据流不具可移植性,并且 不应该 (SHOULD NOT) 在公开可用的软件或数据流中使用。如果私有关键数据块对于某个应用程序是必不可少的,它 应当 (SHOULD) 出现在数据流的开头附近,以便标准解码器在发现无法处理该数据流之前不必读取很远。

关于定义私有数据块的更多准则,请参见 B. 私有块类型指南

5.8 私有字段值

以下字段中大于或等于 128 的值是 私有字段值

这些 私有字段值 既未在本规范中定义,也未保留。

私有字段值 可以 (MAY) 用于实验性或私有语义。

私有字段值 不应该 (SHOULD NOT) 出现在公开可用的软件或数据流中,因为它们可能导致 PNG 解码器无法读取数据流,详情请见 13. PNG 解码器和查看器

6. 参考图像到 PNG 图像的转换

6.1 颜色类型和值

正如 4.5 PNG 图像 中所解释的,有五种类型的 PNG 图像。对应于每种类型的是一个 颜色类型 (color type),它是以下值的总和:1(使用调色板)、2(使用 真彩色 (truecolor))和 4(使用 Alpha 通道)。灰度 (greyscale)真彩色 图像可以具有显式的 Alpha 通道。PNG 图像类型及相应的 颜色类型 列在 9 中。

9 PNG 图像类型和颜色类型
PNG 图像类型 颜色类型
灰度 0
真彩色 2
索引色 3
带 Alpha 的灰度 4
带 Alpha 的真彩色 6

每种 PNG 图像类型允许的位深度和采样深度列在 图像头 中。

如果指示了传递曲线(由 gAMAsRGBiCCP)或 cICP,则灰度样本表示亮度;否则表示与设备相关的灰度。如果指示了色彩空间(由 gAMAcHRMsRGBiCCPcICP),则 RGB 样本表示校准后的颜色信息;否则表示未经校准的、与设备相关的颜色。

样本值不一定与光强度成比例;gAMA 数据块指定了样本值与显示输出强度之间的关系。强烈建议查看器进行适当补偿。参见 4.3 色彩空间13.13 解码器 Gamma 处理C. Gamma 和色度

6.2 Alpha 表示法

在 PNG 数据流中,透明度可以通过四种方式之一表示,具体取决于 PNG 图像类型(参见 4.4.1 Alpha 分离4.4.4 Alpha 压缩)。

  1. 带 Alpha 通道的真彩色带 Alpha 通道的灰度:Alpha 通道是图像数组的一部分。
  2. 真彩色灰度tRNS 数据块包含单个像素值,用于区分完全透明的像素和完全不透明的像素。
  3. 索引色tRNS 数据块包含 Alpha 表,该表将 Alpha 样本与每个调色板条目关联起来。
  4. 真彩色灰度索引色:不存在 tRNS 数据块,且所有像素均为完全不透明。

图像数组中包含的 Alpha 通道具有 8 位或 16 位样本,与其它样本大小相同。每个像素的 Alpha 样本存储在像素的灰度或 RGB 样本之后。Alpha 值为零表示完全透明,值为 2采样深度 - 1 表示完全不透明。中间值表示部分透明的像素,这些像素可以与背景图像进行 合成 (composited),以产生最终图像。

像素中的颜色值不会预先乘以分配给该像素的 Alpha 值。此规则有时被称为“非关联”或“非预乘”Alpha。(另一种常见的技术是存储乘以 Alpha 值后的样本值;实际上,这样的图像已经在黑色背景上进行了 合成。PNG 使用预乘 Alpha。因此,图像编辑器可以获取一个 PNG 图像并轻松更改其透明度。)参见 12.3 Alpha 通道创建13.16 Alpha 通道处理

7. 将 PNG 图像编码为 PNG 数据流

7.1 整数和字节序

所有需要多于一个字节的整数都应采用 网络字节序(如图 17 所示):最高有效字节在前,然后是按重要性递减顺序排列的较低有效字节(双字节整数为 MSB LSB,四字节整数为 MSB B2 B1 LSB)。一个字节的最高位(值 128)编号为位 7;最低位(值 1)编号为位 0。除非另有说明,否则数值为无符号。明确标为有符号的值采用补码表示法。

PNG 四字节无符号整数限制在 0 到 231-1 的范围内,以适应对无符号四字节值处理有困难的编程语言。

17 PNG 中的整数表示

7.2 扫描线

PNG 图像(或通道,参见 8. 隔行扫描和通道提取)是一个矩形像素数组,像素在每行扫描线中从左到右排列,扫描线从上到下排列。每个像素的大小由每像素位数决定。

扫描线内的像素始终打包成字节序列,像素之间没有浪费的位。扫描线始终从字节边界开始。允许的位深度和 颜色类型 受到限制,以便在所有情况下打包都简单高效。

颜色类型 0(灰度)的 PNG 图像中,每个像素是一个单一采样,其精度可能小于一个字节(1、2 或 4 位)。这些采样被打包到字节中,其中最左侧的采样位于字节的高位,后面是扫描线的其余采样。

颜色类型 3(索引色)的 PNG 图像中,每个像素是一个单一调色板索引。这些索引以与 颜色类型 0 的采样相同的方式打包到字节中。

当每个字节有多个像素时,扫描线最后一个字节的一些低位可能不会被使用。这些未使用位的内容未指定。

索引色 的 PNG 图像可能具有位深度为 16 的采样值。此类采样值采用 网络字节序MSB 优先,LSB 第二)。PNG 仅允许在 8 位和 16 位采样中使用多采样像素,因此单个像素的多个采样永远不会被打包到一个字节中。

7.3 过滤

过滤方法 (filter method) 是一种应用于 扫描线 数组的变换,旨在提高其可压缩性。

PNG 标准化了一种 过滤方法 和几种可用于准备 图像数据 以进行压缩的过滤器类型。它将字节序列变换为等长的字节序列,并在前面加上一个过滤器类型字节(参见 18 中的示例)。

编码器应仅对隔行扫描的 PNG 图像使用单一的 过滤方法,但可以对缩减图像中的每一行扫描线使用不同的过滤器类型。智能编码器可以在不同的扫描线之间切换过滤器。选择采用哪种过滤器的方法留给编码器决定。

过滤器类型字节不被视为 图像数据 的一部分,但它被包含在发送到压缩步骤的数据流中。参见 9. 过滤

18 序列化和过滤扫描线

8. 隔行扫描和通道提取

引言

通道提取(参见 图 4.8)将 PNG 图像拆分为一系列缩减图像(隔行扫描 PNG 图像),其中第一幅图像定义了粗略视图,后续图像增强此粗略视图,直到最后一幅图像完成 PNG 图像。这允许解码器对隔行扫描的 PNG 图像进行渐进式显示,并允许图像在动态显示时“淡入”。平均而言,隔行扫描会略微扩展数据流大小,但它可以让用户更快地获得有意义的显示效果。

8.1 隔行扫描方法

本国际标准定义了两种隔行扫描方法,即方法 0 和方法 1。其他隔行扫描方法的值保留以用于未来的标准化。

使用方法 0(空方法),像素从左到右依次提取,扫描线从上到下依次提取。隔行扫描的 PNG 图像是单一的缩减图像。

方法 1,称为 Adam7,定义了图像的七个不同通道。每个通道传输参考图像中像素的子集。每个像素传输所在的通道(从 1 到 7 编号)定义为在整个图像上复制以下 8x8 模式,从左上角开始

1 6 4 6 2 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
3 6 4 6 3 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7

图 4.8 显示了方法 1 的七个通道。在每个通道内,所选像素在扫描线内从左到右传输,所选扫描线从上到下依次传输。例如,通道 2 包含扫描线 0、8、16 等的像素 4、12、20 等(其中扫描线 0,像素 0 是左上角)。最后一个通道包含所有扫描线 1、3、5 等。传输顺序的定义使得在通道中传输的所有扫描线将具有相同数量的像素;这对于正确应用某些过滤器是必要的。隔行扫描的 PNG 图像由七个缩减图像的序列组成。例如,如果 PNG 图像为 16x16 像素,则第三个通道将是包含两行扫描线的缩减图像,每行包含四个像素(参见 图 4.8)。

未完全填满整数个字节的扫描线按 7.2 扫描线 中的定义进行填充。

注意 如果参考图像包含少于五列或少于五行,则某些通道将为空。

9. 过滤

9.1 过滤方法和过滤类型

过滤通过提高压缩率来转换 PNG 图像。整个过程描述在 7 中,而序列化和过滤扫描线的具体细节显示在 18 中。

PNG 允许多种 过滤方法。隔行扫描图像中的所有缩减图像都应使用单一的 过滤方法。本规范仅定义了 过滤方法 0。其他 过滤方法 保留用于未来标准化。过滤方法 0 提供了一组五种过滤器类型,每个缩减图像中的各个扫描线可以使用不同的过滤器类型。

PNG 对应用于隔行扫描 PNG 图像的过滤器类型没有额外限制。然而,过滤器类型在所有类型的数据上效果并不相同。参见 12.7 过滤器选择

过滤将扫描线中的字节序列转换为等长的字节序列,并在前面加上过滤器类型。过滤器类型字节仅与非空扫描线相关联。在空通道中不存在过滤器类型字节。参见 13.10 隔行扫描和渐进式显示

9.2 过滤方法 0 的过滤类型

无论图像的位深度或 颜色类型 如何,过滤器都应用于字节而不是像素。过滤器对表示为 7.2 扫描线 中所述的扫描线形成的字节序列进行操作。如果图像包含 Alpha 通道,则 Alpha 数据以与 图像数据 相同的方式进行过滤。

过滤器可以使用以下字节的原始值来生成新的字节值

10 命名过滤字节
名称 定义
x 正在被过滤的字节;
a 对应于包含 x 的像素之前的像素中的 x 字节(或当位深度小于 8 时,x 之前的字节);
b 对应于前一条扫描线中 x 的字节;
c 对应于包含 b 的像素之前的像素中的 b 字节(或当位深度小于 8 时,b 之前的字节)。
19 过滤字节 a、b 和 c 相对于 x 的位置

19 显示了字节 xabc 的相对位置。

过滤方法 0 定义了五种基本过滤器类型,列于 11Orig(y) 表示字节 y 的原始(未过滤)值。Filt(y) 表示应用过滤器类型后的值。Recon(y) 表示应用相应的重构函数后的值。Paeth 过滤器类型 PaethPredictor [Paeth] 定义如下。

过滤方法 0 精确指定了这五种过滤器类型,不得扩展。这确保了解码器无需解压缩数据即可确定它是否包含不受支持的过滤器类型:只需检查 11.2.1 IHDR 图像头 中的 过滤方法 即可。

11 过滤器类型
类型 名称 过滤器功能 重构功能
0 Filt(x) = Orig(x) Recon(x) = Filt(x)
1 Sub Filt(x) = Orig(x) - Orig(a) Recon(x) = Filt(x) + Recon(a)
2 向上 (Up) Filt(x) = Orig(x) - Orig(b) Recon(x) = Filt(x) + Recon(b)
3 Average Filt(x) = Orig(x) - floor((Orig(a) + Orig(b)) / 2) Recon(x) = Filt(x) + floor((Recon(a) + Recon(b)) / 2)
4 Paeth Filt(x) = Orig(x) - PaethPredictor(Orig(a), Orig(b), Orig(c)) Recon(x) = Filt(x) + PaethPredictor(Recon(a), Recon(b), Recon(c))

对于所有过滤器,扫描线中第一个像素“左侧”的字节应视为零。对于引用前一条扫描线的过滤器,整个前一条扫描线以及前一条扫描线中第一个像素“左侧”的字节应被视为缩减图像第一条扫描线的零。

要撤消过滤器的效果,需要前一条扫描线上相同位置像素、当前像素正上方像素以及正上方像素左侧像素的解码值。

使用模 256 无符号算术,以便输入和输出都适合字节。无论位深度如何,过滤器都应用于每个字节。Filt 值序列作为过滤后的扫描线传输。

9.3 过滤类型 3:平均值 (Average)

Orig(a) + Orig(b) 应在不溢出的情况下执行(至少使用九位算术)。floor() 表示如果除法有余数,结果向下取整到下一个整数;换句话说,它是整数除法或右移操作。

9.4 过滤类型 4:Paeth 预测

Paeth 过滤器类型计算三个相邻像素(左、上、左上)的简单线性函数,然后选择最接近计算值的相邻像素作为预测值。本规范中使用的算法是 Alan W. Paeth [Paeth] 技术的一种改编。

PaethPredictor 函数定义在下面的代码中。该函数的逻辑以及字节 abcx 的位置显示在 20 中。Pr 是字节 x 的预测值。

p = a + b - c
pa = abs(p - a)
pb = abs(p - b)
pc = abs(p - c)
if pa <= pb and pa <= pc then Pr = a
else if pb <= pc then Pr = b
else Pr = c
return Pr
20 PaethPredictor 函数

PaethPredictor 函数内的计算应准确执行,且不得溢出。

执行比较的顺序至关重要,不得更改。该函数试图确定图像梯度在三个方向(垂直、水平或对角线)中的哪一个方向上最小。

编码器和解码器使用完全相同的 PaethPredictor 函数。

10. 压缩

10.1 压缩方法 0

本国际标准仅定义了 PNG 压缩方法 0。其他压缩方法的值保留用于未来的标准化。PNG 压缩方法 0 是带有滑动窗口(它是 deflate 流中出现的距离的上限)的 deflate 压缩,最大为 32768 字节。Deflate 压缩源自 LZ77

PNG 内的 Deflate 压缩数据流存储在 zlib 格式中,其结构为

zlib 压缩方法/标志代码 1 字节
附加标志/校验位 1 字节
压缩数据块 n 字节
校验值 4 字节

zlib 指定于 [rfc1950]。

对于 PNG 压缩方法 0,zlib 压缩方法/标志代码应指定方法代码 8(deflate 压缩)和不超过 32768 字节的 LZ77 窗口大小。zlib 压缩方法编号与 IHDR 块中的 PNG 压缩方法编号不同。附加标志不得指定预设字典。

如果要压缩的数据包含 16384 字节或更少,PNG 编码器可以通过向上取整到 2 的幂(最小 256)来设置窗口大小。这减少了编码和解码所需的内存,而不会对压缩比产生负面影响。

zlib 数据流中的压缩数据存储为一系列块,每个块可以表示原始(未压缩)数据、使用固定 Huffman 编码的 LZ77 压缩数据,或使用自定义 Huffman 编码的 LZ77 压缩数据。最后一个块中的标记位将其标识为最后一个块,允许解码器识别压缩数据流的结束。关于压缩算法和编码的更多详细信息在 deflate 规范 [rfc1951] 中给出。

存储在 zlib 数据流末尾的校验值是根据数据流表示的未压缩数据计算得出的。用于计算此值的算法与用于 PNG 数据块 CRC 字段值的 CRC 计算不同。zlib 校验值主要用作交叉检查,以验证 deflate 算法实现是否正确。验证各个 PNG 数据块的 CRC 提供了 PNG 数据流未受损传输的置信度。

10.2 过滤扫描线序列的压缩

过滤后的扫描线序列被压缩,生成的压缩数据流被拆分为 IDAT 数据块。所有 IDAT 数据块内容的串联构成了 zlib 数据流。此数据流解压缩后得到过滤后的 图像数据

重要的是要强调,IDAT 数据块之间的边界是任意的,可以出现在 zlib 数据流中的任何位置。IDAT 数据块边界与 deflate 块边界或 zlib 数据或任何其他特征之间不一定存在相关性。例如,完全可能出现最终的 zlib 校验值被拆分在 IDAT 数据块之间的情况。

同样,图像数据 的结构(即扫描线边界)与 deflate 块边界或 IDAT 数据块边界之间没有必需的相关性。完整的过滤后 PNG 图像由一个存储在多个 IDAT 数据块中的单一 zlib 数据流表示。

10.3 压缩的其他用途

PNG 还在 iTXtiCCPzTXt 数据块中使用压缩方法 0。与 图像数据 不同,此类数据流不会跨越数据块拆分;每个此类数据块包含一个独立的 zlib 数据流(参见 10.1 压缩方法 0)。

11. 数据块规范

11.1 概览

本条款定义了本规范中使用的数据块。

11.2 关键数据块

引言

关键数据块 (critical chunk) 是指成功从 PNG 数据流中解码出 PNG 图像所绝对必需的数据块。扩展数据块可以定义为关键数据块(参见 14. 编辑器),尽管强烈不鼓励这种做法。

有效的 PNG 数据流应以 PNG 签名开头,紧随其后的是 IHDR 数据块,然后是一个或多个 IDAT 数据块,并应以 IEND 数据块结束。在 PNG 数据流中只允许存在一个 IHDR 数据块和一个 IEND 数据块。

11.2.1 IHDR 图像头

四字节数据块类型字段包含十六进制值

49 48 44 52

IHDR 数据块应是 PNG 数据流中的第一个数据块。它包含

宽度 4 字节
高度 4 字节
位深度 1 字节
颜色类型 1 字节
压缩方法 1 字节
过滤方法 1 字节
交错方法 1 字节

宽度和高度给出像素单位的图像尺寸。它们是 PNG 四字节无符号整数。零是无效值。

位深度是一个单字节整数,给出每个采样或每个调色板索引的位数(而非每像素位数)。有效值为 1、2、4、8 和 16,尽管并非所有颜色类型都允许所有值。参见 6.1 颜色类型和值

颜色类型 是一个单字节整数。

对每种 颜色类型 的位深度限制旨在简化实现并禁止压缩效果不佳的组合。允许的组合定义在 12 中。

12 颜色类型 和位深度的允许组合
PNG 图像类型 颜色类型 允许的位深度 解释
灰度 0 1, 2, 4, 8, 16 每个像素是一个灰度采样
真彩色 2 8, 16 每个像素是一个 R、G、B 三元组
索引色 3 1, 2, 4, 8 每个像素是一个调色板索引;必须出现一个 PLTE 数据块。
带 Alpha 的灰度 4 8, 16 每个像素是一个灰度采样后跟一个 Alpha 采样。
带 Alpha 的真彩色 6 8, 16 每个像素是一个 R、G、B 三元组后跟一个 Alpha 采样。

除了 索引色 PNG 图像(颜色类型 3)外,采样深度与位深度相同,其中采样深度始终为 8 位(参见 4.5 PNG 图像)。

压缩方法是一个单字节整数,指示用于压缩 图像数据 的方法。本规范仅定义了压缩方法 0(带有最大 32768 字节滑动窗口的 deflate 压缩)。所有符合规范的 PNG 图像都应使用此方案压缩。

过滤方法是一个单字节整数,指示压缩前应用于 图像数据 的预处理方法。本规范仅定义了 过滤方法 0(具有五种基本过滤器类型的自适应过滤)。详情请参见 9. 过滤

交错方法是一个单字节整数,指示 图像数据 的传输顺序。本规范定义了两个值:0(无交错)或 1(Adam7 交错)。详情请参见 8. 隔行扫描和通道提取

11.2.2 PLTE 调色板

四字节数据块类型字段包含十六进制值

50 4C 54 45

PLTE 数据块包含 1 到 256 个调色板条目,每个条目是一个三字节序列,形式为

红色 1 字节
绿色 1 字节
蓝色 1 字节

条目数量由数据块长度确定。不能被 3 整除的数据块长度是错误的。

对于 颜色类型 3,该数据块必须出现,并且对于 颜色类型 2 和 6,它可能出现;它不得出现在 颜色类型 0 和 4 中。不得有超过一个 PLTE 数据块。

对于 颜色类型 3(索引色),必须有 PLTE 数据块。PLTE 中的第一个条目由像素值 0 引用,第二个由像素值 1 引用,依此类推。调色板条目数不得超过图像位深度可表示的范围(例如,位深度为 4 时,24 = 16)。允许拥有的条目少于位深度所允许的数量。在这种情况下,在 图像数据 中找到的任何超出范围的像素值都是错误的。

对于 颜色类型 2 和 6(真彩色带 Alpha 通道的真彩色),PLTE 数据块是可选的。如果存在,它提供了一组建议的颜色(1 到 256 种),如果无法直接显示真彩色图像,则可以将真彩色图像量化为这些颜色。然而,建议将 sPLT 数据块用于此目的,而不是 PLTE 数据块。如果 PLTEsPLT 数据块都不存在且图像无法直接显示,则查看系统必须执行量化。然而,通常最好由 PNG 编码器一次性完成颜色的选择。(参见 12.5 建议调色板。)

请注意,无论图像位深度如何,调色板每个采样使用 8 位(1 字节)。特别是,即使它是 16 位 真彩色 图像的建议量化版本,调色板的深度也是 8 位。

没有要求调色板条目必须全部由图像使用,也不要求它们必须全部不同。

11.2.3 IDAT 图像数据

四字节数据块类型字段包含十六进制值

49 44 41 54

IDAT 数据块包含实际的 图像数据,即压缩算法的输出流。详情请参见 9. 过滤10. 压缩

可能有多个 IDAT 数据块;如果是这样,它们应连续出现,中间没有其他数据块。压缩数据流是所有 IDAT 数据块数据字段内容的串联(请注意数据字段 可能是零长度)。

有些图像在最后一个 IDAT 数据块末尾有未使用的尾随字节。当存储整个缓冲区而不是仅存储缓冲区中已使用的部分时,可能会发生这种情况。这是不可取的。最好是编码器不包含这些未使用的字节。如果必须包含,将这些字节设置为零将防止意外的数据共享。解码器应该忽略这些尾随字节。

11.2.4 IEND 图像结尾

四字节数据块类型字段包含十六进制值

49 45 4E 44

IEND 数据块标记 PNG 数据流的结束。数据块的数据字段为空。

11.3 辅助数据块

引言

本规范中定义的辅助数据块列在 4.8.2 数据块类型 中。这不是它们在 PNG 数据流中出现的顺序。解码器可以忽略辅助数据块。对于每个辅助数据块,所描述的操作均假设解码器没有忽略该数据块。

11.3.1 透明度信息

11.3.1.1 tRNS 透明度

四字节数据块类型字段包含十六进制值

74 52 4E 53

tRNS 数据块指定与调色板条目关联的 Alpha 值(用于 索引色 图像)或单个透明颜色(用于 灰度真彩色 图像)。tRNS 数据块包含

颜色类型 0
灰度采样值 2 字节
颜色类型 2
红色采样值 2 字节
绿色采样值 2 字节
蓝色采样值 2 字节
颜色类型 3
调色板索引 0 的 Alpha 值 1 字节
调色板索引 1 的 Alpha 值 1 字节
...等等... 1 字节

对于 颜色类型 3(索引色),tRNS 数据块包含一系列单字节 Alpha 值,对应于 PLTE 数据块中的条目。每个条目指示对应调色板索引的像素应被视为具有指定的 Alpha 值。Alpha 值的解释与 8 位全 Alpha 通道中的相同:0 表示完全透明,255 表示完全不透明,无论图像位深度如何。tRNS 数据块所包含的 Alpha 值不得超过调色板条目数,但 tRNS 数据块所包含的值可以少于调色板条目数。在这种情况下,假定所有剩余调色板条目的 Alpha 值为 255。在通常仅需要使调色板索引 0 透明的情况下,仅需一个单字节的 tRNS 数据块;当所有调色板索引都是不透明的时,可以省略 tRNS 数据块。

对于 颜色类型 0 或 2,无论图像位深度如何,每个采样使用两个字节(参见 7.1 整数和字节序)。指定灰度采样值或 RGB 采样值的像素被视为透明(等同于 Alpha 值 0);所有其他像素被视为完全不透明(Alpha 值为 2位深度-1)。如果图像位深度小于 16,则使用最低有效位。编码器应将其他位设置为 0,解码器在使用该值之前必须将其他位屏蔽为 0。

tRNS 数据块不得出现在 颜色类型 4 和 6 中,因为在这些情况下已经存在完整的 Alpha 通道。

注意 对于 16 位 灰度真彩色 数据,如 13.12 采样深度缩放 所述,仅 tRNS 数据块中完整的 16 位值匹配的像素 是透明的。解码器必须推迟任何采样深度缩放,直到像素被测试过透明度之后。

11.3.2 色彩空间信息

11.3.2.1 cHRM 原色色度与白点

四字节数据块类型字段包含十六进制值

63 48 52 4D

cHRM 数据块可用于指定 PNG 图像 中使用的红、绿、蓝显示基色的 1931 CIE x,y 色度,以及引用的 白点 (white point)。有关更多信息,参见 C. Gamma 和色度iCCPsRGB 数据块提供了对色彩管理和控制更高级的支持。

cHRM 数据块包含

13 cHRM 数据块组件
名称 大小
白点 x 4 字节
白点 y 4 字节
红 x 4 字节
红 y 4 字节
绿 x 4 字节
绿 y 4 字节
蓝 x 4 字节
蓝 y 4 字节

每个值都编码为 PNG 四字节无符号整数,表示 xy 值乘以 100000。

0.3127 的值将存储为整数 31270。

cHRM 数据块允许在所有 PNG 数据流中使用,尽管它对于 灰度 图像几乎没有价值。

除非它是解码器所能理解的 最高优先级的颜色数据块,否则此数据块将被忽略。

11.3.2.2 gAMA 图像伽马

四字节数据块类型字段包含十六进制值

67 41 4D 41

gAMA 数据块指定一个 Gamma 值

实际上,指定期望的显示输出强度是不够的。还需要指定期望输出的观看条件。对于 gAMA,这些是 sRGB 规范 [SRGB] 的参考观看条件。不同观看条件的调整通常由色彩管理系统处理。如果没有执行调整,误差通常很小。希望获得高色彩保真度的应用程序可能希望使用 sRGBiCCP 数据块。

gAMA 数据块包含

图像 Gamma 4 字节

该值编码为 PNG 四字节无符号整数,表示 Gamma 值 乘以 100000。

1/2.2 的 Gamma 值 将存储为整数 45455。

有关更多信息,请参见 12.1 编码器 Gamma 处理13.13 解码器 Gamma 处理

除非它是解码器所能理解的 最高优先级的颜色数据块,否则此数据块将被忽略。

11.3.2.3 iCCP 嵌入式 ICC 配置文件

四字节数据块类型字段包含十六进制值

69 43 43 50

iCCP 数据块包含

配置文件名称 1-79 字节(字符串)
空分隔符 1 字节(空字符)
压缩方法 1 字节
压缩配置文件 n 字节

配置文件名称可以是引用配置文件的任何方便名称。它区分大小写。配置文件名称应仅包含可打印的 Latin-1 字符和空格(仅允许代码点 0x20-7E 和 0xA1-FF)。不允许使用前导、尾随和连续空格。本规范定义的唯一压缩方法是方法 0(带有 deflate 压缩的 zlib 数据流,参见 10.3 压缩的其他用途)。压缩方法条目之后是构成数据块其余部分的压缩配置文件。对此数据流进行解压缩即可得到嵌入的 ICC 配置文件。

如果存在 iCCP 数据块,则图像采样符合国际色彩联盟 [ICC][ISO_15076-1] 定义的嵌入 ICC 配置文件所代表的色彩空间。ICC 配置文件的色彩空间应为彩色图像(颜色类型 2、3 和 6)的 RGB 色彩空间,或者是 灰度 图像(颜色类型 0 和 4)的灰度色彩空间。鼓励写入 iCCP 数据块的 PNG 编码器同时写入近似该 ICC 配置文件的 gAMAcHRM 数据块,以便与不使用 iCCP 数据块的应用程序兼容。

除非它是解码器所能理解的 最高优先级的颜色数据块,否则此数据块将被忽略。

除非存在 cICP 数据块,否则 PNG 数据流最多应包含一个嵌入的配置文件,无论是显式使用 iCCP 指定还是隐式使用 sRGB 数据块指定。

11.3.2.4 sBIT 有效位

四字节数据块类型字段包含十六进制值

73 42 49 54

为了简化解码器,PNG 规定只能使用特定的采样深度,并进一步规定采样值应缩放到该采样深度下的全范围可能值。sBIT 数据块定义了原始有效位数的数量(可以小于或等于采样深度)。这使得 PNG 解码器即使在数据具有 PNG 本身不支持的采样深度时,也能无损地恢复原始数据。

sBIT 数据块包含

14 sBIT 数据块内容
颜色类型 0
有效灰度位数 1 字节
颜色类型 2 和 3
有效红色位数 1 字节
有效绿色位数 1 字节
有效蓝色位数 1 字节
颜色类型 4
有效灰度位数 1 字节
有效 Alpha 位数 1 字节
颜色类型 6
有效红色位数 1 字节
有效绿色位数 1 字节
有效蓝色位数 1 字节
有效 Alpha 位数 1 字节

sBIT 中指定的每个深度都必须大于零且小于或等于采样深度(索引色图像为 8,其他颜色类型则为 IHDR 中给定的位深度)。注意,sBIT 不提供 tRNS 数据块所暗示的 Alpha 通道的采样深度;在这种情况下,Alpha 通道的所有采样位都应被视为有效的。如果不存在 sBIT 数据块,则所有通道的所有采样位都应被视为有效的。

11.3.2.5 sRGB 标准 RGB 色彩空间

四字节数据块类型字段包含十六进制值

73 52 47 42

如果存在 sRGB 数据块,则图像采样符合 sRGB 色彩空间 [SRGB],并应使用国际色彩联盟 [ICC] 或 [ICC-2] 定义的指定渲染意图进行显示。

sRGB 数据块包含

15 sRGB 数据块内容
名称 大小
渲染意图 1 字节

渲染意图定义了以下值

16 渲染意图值
名称 描述
0 可感知 (Perceptual) 适用于优先考虑对输出设备色域进行良好适应,而牺牲比色精度的图像,例如照片。
1 相对比色 (Relative colorimetric) 适用于需要色彩外观匹配(相对于输出设备的白点)的图像,例如徽标。
2 饱和度 (Saturation) 适用于优先考虑保持饱和度而牺牲色相和明度的图像,例如图表和图形。
3 绝对比色 (Absolute colorimetric) 适用于需要保持绝对比色的图像,例如发送至不同输出设备的图像预览(校样)。

建议写入 sRGB 数据块的 PNG 编码器同时也写入 gAMA 数据块(以及可选的 cHRM 数据块),以兼容不使用 sRGB 数据块的解码器。只能使用以下值。

17 sRGB 的 gAMA 和 cHRM 值
gAMA
伽马值 45455
cHRM
白点 x 31270
白点 y 32900
红 x 64000
红 y 33000
绿 x 30000
绿 y 60000
蓝 x 15000
蓝 y 6000

除非它是解码器所能理解的 最高优先级的颜色数据块,否则此数据块将被忽略。

建议 sRGBiCCP 数据块不要同时出现在同一个 PNG 数据流中。

11.3.2.6 cICP 用于视频信号类型识别的编码独立码点

四字节数据块类型字段包含十六进制值

63 49 43 50

如果存在,cICP 数据块使用 [ITU-T-H.273] 中指定的代码点来定义图像的色彩空间(基色)、传递函数、矩阵系数和缩放因子。在处理图像时(包括解码或渲染图像时),应当使用视频格式信号。

cICP 数据块由四个 1 字节无符号整数组成,用于标识上述特征。

以下规定了 cICP 数据块的语法

18 cICP 数据块组件
名称 大小
原色 (Color Primaries) 1 字节
传递函数 (Transfer Function) 1 字节
矩阵系数 (Matrix Coefficients) 1 字节
视频全范围标志 (Video Full Range Flag) 1 字节

cICP 数据块的每个字段对应 [ITU-T-H.273] 中的同名参数。

RGB 是目前 PNG 中唯一支持的颜色模型,因此 Matrix Coefficients 应设置为 0

如果 Video Full Range Flag0窄范围图像),推荐做法是在扩展范围内定义传递函数(如 EOTF 或反向 OETF),以便包含负值。具体做法如下

out = sign(in) * TransferFunction(abs(in))

cICP 数据块 必须位于 PLTEIDAT 数据块之前。

如果解码器能够识别此数据块,它即为最高优先级的颜色数据块

与使用 sRGB 数据块紧凑地标记 sRGB 图像的方式类似,cICP 可用于紧凑地标记 Display P3 图像 [Display-P3]。

11.3.2.7 mDCV 母版显示色彩体积

四字节数据块类型字段包含十六进制值

6D 44 43 56

如果存在,mDCV 数据块表征内容创作点使用的母版显示颜色容量 (Mastering Display Color Volume),如 [SMPTE-ST-2086] 所指定。mDCV 数据块提供信息性静态元数据,允许目标(消费级)显示器通过比较其固有能力与原始母版显示器的能力,从而优化其色调映射决策。

mDCV 通常与 PQ [ITU-R-BT.2100] 传递函数以及额外的 cLLI 元数据一起使用,通常被称为 [HDR10](带 ST 2086 静态元数据、MaxFALL 和 MaxCLL 的 PQ)。mDCV 数据块也可包含在 HLG [ITU-R-BT.2100] 和 SDR 图像格式中(例如 [ITU-R-BT.709])。

由于 mDCV 最初是作为旨在优化视频显示目标上图像色调映射的补充静态元数据创建的,因此使用 mDCV 时必须附带 cICP 数据块,以确立图像内容的基本特征。原色和白点特征可从 cICP 数据块格式中派生。关于使用 HDR [ITU-R-BT.2100] 和 SDR [ITU-R-BT.709] 的图像的最常见用例的具体示例,可在 [ITU-T-Series-H-Supplement-19] 中找到。基本 (cICP) 特征加上补充 (mDCV) 静态元数据可提供宝贵信息,以优化色调映射决策。

Issue #319 讨论了当存在 mDCV 数据块时的色调映射行为。

对于 SDR 图像,如果 mDCV 显示器的最小/最大亮度未知,则可以从 [ITU-T-Series-H-Supplement-19] 表 11 或相关 SDR 规范中的值推导出默认特征。目前,尚无已发布的标准化方法将 SDR 图像信号从其默认观看条件(显示亮度及环境照明)转换为 mDCV 数据块中标记的条件。

以下规定了 mDCV 数据块的语法

19 mDCV 数据块组件
名称 大小 除数 (Divisor value)
母版显示原色色度(R、G、B 的 CIE 1931 x,y 12 字节 0.00002
母版显示白点色度(CIE 1931 x,y 4 字节 0.00002
母版显示最大亮度(以 cd/m2 为单位) 4 字节 0.0001
母版显示最小亮度(以 cd/m2 为单位) 4 字节 0.0001

原色被编码为三对 PNG 双字节无符号整数,顺序为 x 然后 y,每一对代表除以除数后的 x 或 y 原色色度值。排序方式以 x 色度最大的原色开始,其次是 y 色度最大的原色,最后是剩余的原色。对于 RGB 色彩空间,这对应于 R、G、B 的顺序。

白点被编码为一对 PNG 双字节无符号整数,顺序为 x 然后 y,每一对代表除以除数后的 x 或 y 白点色度值。

最大和最小亮度值被编码为 PNG 四字节无符号整数,表示除以除数后的绝对亮度值(单位:cd/m2)。

除数用于将实际值映射到存储值。例如,对于原色和白点的无量纲除数 0.00002,将色度 (0.6800, 0.3200) 存储为 {34000, 16000}。

mDCV 数据块 必须位于 PLTEIDAT 数据块之前。

以下是 [ITU-R-BT.2100] HDR 的 mDCV 示例。

以下是 [Display-P3] SDR 的 mDCV 示例。

11.3.2.8 cLLI 内容光照水平信息

四字节数据块类型字段包含十六进制值

63 4C 4C 49

如果存在,cLLI 数据块标识 HDR 内容的两个特征

cLLI 数据块添加了静态元数据,提供了优化关联内容向特定目标显示器色调映射的机会。这是通过根据目标显示器的特定峰值亮度能力调整内容的色调映射以防止裁切来实现的。色调映射优化方法目前是主观的。

MaxCLL(最大内容光照水平)使用静态元数据值来指示整个回放序列中任何单个像素的最大光照水平(以 cd/m2 为单位,也称为尼特)。通常存在一种算法过滤器,用于消除因处理或噪声产生的虚假值,这些值可能会对下游预期的色调映射产生负面影响。

MaxFALL(最大帧平均光照水平)使用静态元数据值来指示整个回放序列中平均光照水平的最大值(以 cd/m2 为单位,也称为尼特)。MaxFALL 的计算方法是:首先对每一帧中所有像素的解码亮度值求平均,然后使用该值中最大的那一帧的结果。

MaxCLL 和 MaxFALL 值被编码为 PNG 四字节无符号整数

[CTA-861.3-A] 描述了生成 cLLI 值的计算方法,但未指定任何过滤。 [HDR-Static-Meta] 描述了一种改进的方法,可以排除统计异常值、重采样过滤器引起的噪声或振铃效应,推荐用于实际实施。

[SMPTE-ST-2067-21] 第 7.5 节在 cLLI 值未知且尚未计算的情况下增加了额外信息。

Issue #319 讨论了当存在 cLLI 数据块时的色调映射行为。

分析每一帧

MaxCLL 或 MaxFALL 为零表示该值未知或目前无法计算。

无法计算的一个例子是创建实时动画 PNG 流时,在流结束之前并非所有帧都可用以计算这些值。编码器可能希望最初使用零值,并在流结束时用计算出的值替换它。

以下规定了 cLLI 数据块的语法

20 cLLI 数据块组件
名称 大小 除数 (Divisor value)
最大内容光照水平 (MaxCLL) 4 字节 0.0001 cd/m2
最大帧平均光照水平 (MaxFALL) 4 字节 0.0001 cd/m2

11.3.3 文本信息

引言

PNG 提供了 tEXtiTXtzTXt 数据块,用于存储与图像关联的文本字符串,例如图像描述或版权声明。关键字用于指示每个文本字符串代表的内容。可以出现任意数量的此类文本数据块,并且允许出现多个具有相同关键字的数据块。

11.3.3.1 关键字和文本字符串

以下关键字是预定义的,应在适当时使用。

21 预定义关键字
关键字值 描述
Title 图像的简短(单行)标题或说明
Author 图像创作者的姓名
描述 图像描述(可能很长)
Copyright 版权声明
Creation Time 原始图像创建时间
Software 用于创建图像的软件
Disclaimer 法律声明
Warning 关于内容性质的警告
来源 用于创建图像的设备
Comment 其他评论
XML:com.adobe.xmp 可扩展元数据平台 (XMP) 信息,按 XMP 规范 [XMP] 的要求格式化。为了符合 XMP 标准,建议使用压缩标志设置为 0 的 iTXt,并将语言标签和翻译后的关键字都设置为空字符串。
Collection 图像所属的集合名称。图像可以属于一个或多个集合,每个集合由单独的文本数据块命名。

其他关键字 可以由任何应用程序为私有或一般用途定义。

关键字 应当是:

  • 相当直观,因为目的是让其他人能够理解该数据块包含的内容;以及
  • 经过选择,以尽量减少不同应用程序将同一关键字用于不兼容目的的可能性。

一般用途的关键字 应当列在 [PNG-EXTENSIONS] 中。

关键字只能包含可打印的 Latin-1 [ISO_8859-1] 字符和空格;也就是说,只允许代码点 0x20-7E 和 0xA1-FF。为减少人为误读关键字的机会,关键字中不允许出现前导空格、尾随空格和连续空格,也不允许出现 U+00A0 不换行空格,因为它与普通空格在视觉上无法区分。

关键字的拼写必须与注册的一致,以便解码器在查找特定关键字时可以使用简单的字面比较。特别是,关键字被视为区分大小写。关键字长度限制为 1 到 79 字节。

对于“Creation Time”关键字,日期格式 应当为 RFC 3339 [rfc3339] 日期-时间格式,或 RFC 1123 [rfc1123] 第 5.2.14 节中定义的日期格式。首选 RFC3339 日期-时间格式。此字段的实际格式未定义。

iTXt 数据块使用 UTF-8 编码 [rfc3629],可用于传送任何语言的字符。可以选择压缩 iTXt 数据块中的文本字符串。iTXt 支持 Unicode,因此推荐用于所有文本字符串。此外还有 tEXtzTXt 数据块,其内容仅限于可打印的 Latin-1 字符集加上 U+000A 换行符 (LF)。zTXt 中的文本字符串使用 deflate 压缩算法压缩为 zlib 数据流(参见 10.3 其他压缩用途)。

11.3.3.2 tEXt 文本数据

四字节数据块类型字段包含十六进制值

74 45 58 74

每个 tEXt 数据块包含一个关键字和一个文本字符串,格式为:

Keyword(关键字) 1-79 字节(字符串)
空分隔符 1 字节(空字符)
文本字符串 0 个或更多字节(字符字符串)

关键字和文本字符串由一个零字节(空字符)分隔。关键字和文本字符串都不能包含空字符。文本字符串不是以空字符结尾的(长度由数据块长度决定)。文本字符串的长度可以是从零字节到最大允许数据块大小减去关键字和空字符分隔符长度之间的任何长度。

关键字指示文本字符串代表的信息类型,如 11.3.3.1 关键字和文本字符串 中所述。

文本根据 Latin-1 字符集 [ISO_8859-1] 进行解释。文本字符串可以包含任何 Latin-1 字符。文本字符串中的换行符应表示为单个换行符(十进制 10)。除 Latin-1 中定义的字符和换行符外,其他字符在 tEXt 数据块中没有定义意义。包含 ISO/IEC 8859-1 字符集以外字符的文本应使用 iTXt 数据块进行编码。

11.3.3.3 zTXt 压缩文本数据

四字节数据块类型字段包含十六进制值

7A 54 58 74

zTXttEXt 数据块在语义上是等效的,但建议对存储大块文本使用 zTXt 数据块。

一个 zTXt 数据块包含:

Keyword(关键字) 1-79 字节(字符串)
空分隔符 1 字节(空字符)
压缩方法 1 字节
压缩后的文本数据流 n 字节

关键字和空字符与 tEXt 数据块中的相同。关键字未压缩。压缩方法条目定义所使用的压缩方法。本国际标准中定义的唯一值是 0(deflate 压缩)。其他值留待未来标准化。压缩方法条目后跟构成数据块其余部分的压缩文本数据流。对于压缩方法 0,此数据流是一个带有 deflate 压缩的 zlib 数据流(参见 10.3 其他压缩用途)。解压缩此数据流将得到与等效 tEXt 数据块中存储的文本完全相同的 Latin-1 文本。

11.3.3.4 iTXt 国际化文本数据

四字节数据块类型字段包含十六进制值

69 54 58 74

一个 iTXt 数据块包含:

Keyword(关键字) 1-79 字节(字符串)
空分隔符 1 字节(空字符)
压缩标志 1 字节
压缩方法 1 字节
语言标签 0 个或更多字节(字符字符串)
空分隔符 1 字节(空字符)
翻译后的关键字 0 个或更多字节
空分隔符 1 字节(空字符)
文本 0 个或更多字节

关键字的描述见 11.3.3.1 关键字和文本字符串

压缩标志:0 表示未压缩文本,1 表示压缩文本。仅文本字段可以压缩。压缩方法条目定义所使用的压缩方法。本规范定义的唯一压缩方法是 0(带有 deflate 压缩的 zlib 数据流,参见 10.3 其他压缩用途)。对于未压缩文本,编码器应将压缩方法设置为 0,解码器应忽略它。

语言标签是 [BCP47] 定义的格式良好的语言标签。与关键字不同,语言标签不区分大小写。子标签必须出现在 IANA 语言子标签注册中心中。如果语言标签为空,则语言未指定。语言标签示例包括:enen-GBes-419zh-Hanszh-Hans-CNtlh-Cyrl-AQar-AE-u-nu-latnx-private

翻译后的关键字和文本均使用 UTF-8 编码 [rfc3629],且两者均不得包含零字节(空字符)。与此数据块中的其他文本数据不同,文本不是以空字符结尾的;其长度由数据块长度得出。

翻译后的关键字中不应出现换行符。在文本中,换行符应表示为单个换行符(十六进制 0A)。不鼓励在翻译后的关键字和文本中使用其余控制字符(01-09、0B-1F、7F-9F)。在 UTF-8 中,字符 80-9F(不鼓励使用)与字节 80-9F(通常是必要的)之间存在区别。

翻译后的关键字(如果不为空)应包含关键字向语言标签指示的语言的翻译,并且显示关键字的应用程序也应同时显示翻译后的关键字。

11.3.4 杂项信息

11.3.4.1 bKGD 背景颜色

四字节数据块类型字段包含十六进制值

62 4B 47 44

bKGD 数据块指定了显示图像时使用的默认背景颜色。如果存在任何其他首选背景(无论是用户指定的还是属于较大页面(如浏览器)),都应忽略 bKGD 数据块。bKGD 数据块包含

22 bKGD 数据块内容
颜色类型 0 和 4
灰度 2 字节
颜色类型 2 和 6
红色 2 字节
绿色 2 字节
蓝色 2 字节
颜色类型 3
调色板索引 1 字节

对于 颜色类型 3(索引色),该值为用作背景的颜色的调色板索引。

对于 颜色类型 0 和 4(灰度带 Alpha 的灰度),该值为背景灰度级别,范围为 0 到 (2bitdepth)-1。对于 颜色类型 2 和 6(真彩色带 Alpha 的真彩色),该值是用作背景的颜色,以 RGB 采样给出,范围为 0 到 (2bitdepth)-1。在每种情况下,为保持一致,无论图像位深度如何,每个采样均使用两个字节。如果图像位深度小于 16,则使用最低有效位。编码器应将其他位设置为 0,解码器在使用该值之前必须将其他位掩码为 0。

11.3.4.2 hIST 图像直方图

四字节数据块类型字段包含十六进制值

68 49 53 54

hIST 数据块包含一系列双字节无符号整数

频率 2 字节(无符号整数)
...等等...  

hIST 数据块给出了调色板中每种颜色的近似使用频率。直方图数据块仅在存在 PLTE 数据块时才可出现。如果查看器无法提供调色板中列出的所有颜色,直方图可以帮助它决定如何选择颜色的子集进行显示。

PLTE 数据块中的每个条目应恰好对应一个直方图条目。每个条目与具有该调色板索引的图像像素所占比例成正比;确切的比例因子由编码器选择。

直方图条目是近似的,例外情况是零条目表示相应的调色板条目在图像中完全未被使用。如果存在任何该颜色的像素,则直方图条目必须为非零。

注意:当调色板是 真彩色 图像的建议量化版本时,直方图必然是近似的,因为解码器映射像素到调色板条目的方式可能与编码器不同。在这种情况下,通常不应出现零条目,因为任何条目都可能被使用。

11.3.4.3 pHYs 物理像素尺寸

四字节数据块类型字段包含十六进制值

70 48 59 73

pHYs 数据块指定了显示图像时预期的像素大小或长宽比。它包含

23 pHYs 数据块内容
名称 大小
每单位像素数,X 轴 4 字节(PNG 四字节无符号整数
每单位像素数,Y 轴 4 字节(PNG 四字节无符号整数
单位说明符 1 字节

单位说明符定义了以下值

24 单位说明符值
描述
0 单位未知
1 单位为米

当单位说明符为 0 时,pHYs 数据块仅定义像素长宽比;像素的实际大小保持未指定。

如果不存在 pHYs 数据块,则假定像素为方形,且每个像素的物理尺寸未指定。

11.3.4.4 sPLT 建议调色板

四字节数据块类型字段包含十六进制值

73 50 4C 54

sPLT 数据块包含

25 sPLT 数据块内容
名称 大小
调色板名称 1-79 字节(字符串)
空分隔符 1 字节(空字符)
采样深度 1 字节
红色 1 或 2 字节
绿色 1 或 2 字节
蓝色 1 或 2 字节
Alpha 1 或 2 字节
频率 2 字节
...等等...  

每个调色板条目为 6 或 10 字节,包含 5 个无符号整数(红、蓝、绿、Alpha 和频率)。

可以有任意数量的条目。PNG 解码器根据采样深度字节后剩余的数据块长度确定条目数量。如果 sPLT 采样深度为 8,则该长度必须能被 6 整除;如果采样深度为 16,则必须能被 10 整除。条目应按频率递减顺序出现。不要求条目全部被图像使用,也不要求它们全部不同。

调色板名称可以是引用该调色板的任何方便名称(例如“256 色,包含 Macintosh 默认值”、“256 色,包含 Windows-3.1 默认值”、“最优 512”)。当 PNG 数据流中出现多个调色板时,调色板名称可能有助于选择适当的建议调色板。

调色板名称区分大小写,并受到与 tEXt 数据块的关键字参数相同的限制。调色板名称只能包含可打印的 Latin-1 字符和空格(只允许代码点 0x20-7E 和 0xA1-FF)。不允许使用前导、尾随和连续空格。

sPLT 采样深度应为 8 或 16。

红、绿、蓝和 Alpha 采样各为一或两个字节,具体取决于 sPLT 采样深度,与图像位深度无关。颜色采样不会预乘 Alpha,也不会针对任何背景进行预合成。Alpha 值 0 表示完全透明。Alpha 值 255(当 sPLT 采样深度为 8 时)或 65535(当 sPLT 采样深度为 16 时)表示完全不透明。sPLT 数据块可以出现在任何 颜色类型中。sPLT 中的条目使用与 PNG 图像相同的 伽马值色度值,但可能超出 PNG 图像色彩空间中使用的值范围;例如,在 灰度 PNG 图像中,每个 sPLT 条目通常具有相等的红、绿和蓝值,但这并非必须。同样,即使 PNG 图像不使用透明度,sPLT 条目也可以具有非不透明的 Alpha 值。

每个频率值与在该图像被合成到任何背景之前,图像中在该 RGBA 空间中最接近该调色板条目的像素比例成正比。确切的比例因子由 PNG 编码器选择;建议结果值的范围应适当地填满 0 到 65535 的范围。PNG 编码器可以人为地提高被视为“重要”的颜色的频率,例如徽标中使用的颜色或肖像的面部特征。零是一个有效的频率,表示该颜色是“最不重要”的,或者它很少(如果确实有的话)被使用。当所有频率均为零时,它们是无意义的,也就是说,无法推断出颜色在 PNG 图像中出现的实际频率。

允许有多个 sPLT 数据块,但每个数据块必须具有不同的调色板名称。

11.3.4.5 eXIf 可交换图像文件 (Exif) 配置文件

四字节数据块类型字段包含十六进制值

65 58 49 66

eXIf 数据块的数据段包含一个 Exif 配置文件,格式为 [CIPA-DC-008] 中“4.7.2 Interoperability Structure of APP1 in Compressed Data”指定的格式,不同之处在于不包括 JPEG APP1 标记、长度和 4.7.2(C) 中描述的“Exif ID code”(即“Exif”、NULL 和填充字节)。

eXIf 数据块的大小仅受 PNG 规范施加的最大 231-1 字节的限制。PNG 数据流中只允许一个 eXIf 数据块。

eXIf 数据块包含有关原始图像数据的元数据。如果图像在 Exif 配置文件创建后经过编辑,则此数据可能不再适用于 PNG 图像数据。建议除非解码器具有对 Exif 数据有效性的独立了解,否则该数据应仅被视为具有历史价值。解决 eXIf 数据块中的数据与其他 PNG 数据块中的数据之间可能存在的冲突,超出了本规范的范围。

11.3.4.5.1 eXIf 一般建议

虽然 PNG 规范允许数据块大小最大为 231-1 字节,但应用程序作者应注意,如果 Exif 配置文件要写入 JPEG [JPEG] 数据流,则 eXIf 数据块数据的总长度可能需要调整为不超过 216-9 字节,以便能够放入 JPEG APP1 标记 (Exif) 段。

11.3.4.5.2 eXIf 解码器建议

前两个字节的数据是用于小端序 (Intel) 的“II”或用于大端序 (Motorola) 字节顺序的“MM”。解码器应检查前四个字节以确保它们具有以下十六进制值

49 49 2A 00 (ASCII "II", 16-bit little-endian integer 42)

或者

4D 4D 00 2A (ASCII "MM", 16-bit big-endian integer 42)

所有其他值保留供未来定义。

11.3.4.5.3 eXIf 编码器建议

图像编辑应用程序应考虑 Exif 规范 [CIPA-DC-008] 的 E.3 段,该段讨论了图像更改时更新 Exif 数据的要求。编码器应遵循这些要求,但解码器不应假定该工作已经完成。

虽然编码器可以选择更新它们,但不期望如果主图像发生更改,Exif 配置文件中存在的任何缩略图都会被(或不会被)更新。

11.3.5 时间戳信息

11.3.5.1 tIME 图像最后修改时间

四字节数据块类型字段包含十六进制值

74 49 4D 45

tIME 数据块给出了最后一次图像修改的时间(不是初始图像创建时间)。它包含

26 tIME 数据块内容
名称 大小
年份 2 字节(完整;例如 1995,不是 95)
月份 1 字节 (1-12)
日期 1 字节 (1-31)
小时 1 字节 (0-23)
分钟 1 字节 (0-59)
1 字节 (0-60)(以允许闰秒)

应指定通用时间 (UTC) 而不是本地时间。

tIME 数据块旨在用作在图像数据更改时自动应用并更新的时间戳。

11.3.6 动画信息

11.3.6.1 acTL 动画控制数据块

四字节数据块类型字段包含十六进制值

61 63 54 4C

acTL 数据块声明这是一个动画 PNG 图像,给出了帧数以及循环次数。它包含

帧数 (num_frames) 4 字节
播放次数 (num_plays) 4 字节

每个值被编码为 PNG 四字节无符号整数

num_frames 指示动画中的总帧数。这必须等于 fcTL 数据块的数量。0 不是有效值。1 是有效值,用于单帧 PNG。如果此值不等于实际帧数,则应将其视为错误。

num_plays 指示此动画应播放的次数;如果为 0,则动画应无限期播放。如果非零,动画应在最后一次播放结束时停在最后一帧上。

acTL 数据块必须出现在有效 PNG 数据流内的第一个 IDAT 数据块之前。

为了实现 Web 兼容性,鉴于此数据块的开发部署与将其合并到 PNG 规范之间的时间较长,此数据块名称被特殊定义为私有数据块。

11.3.6.2 fcTL 帧控制数据块

四字节数据块类型字段包含十六进制值

66 63 54 4C

fcTL 数据块定义了单个帧的尺寸、位置、延迟和处置方式。每个帧都需要恰好一个 fcTL 数据块。它包含

27 fcTL 数据块内容
名称 大小
序列号 (sequence_number) 4 字节
width 4 字节
height 4 字节
x 偏移量 (x_offset) 4 字节
y 偏移量 (y_offset) 4 字节
延迟分子 (delay_num) 2 字节
延迟分母 (delay_den) 2 字节
处置操作 (dispose_op) 1 字节
混合操作 (blend_op) 1 字节

sequence_number 定义动画数据块的序列号,从 0 开始。它被编码为 PNG 四字节无符号整数

widthheight 定义随后帧的宽度和高度。它们被编码为 PNG 四字节无符号整数。它们必须大于零。

x_offsety_offset 定义随后帧的 x 和 y 位置。它们被编码为 PNG 四字节无符号整数。0 是一个有效值。

帧必须在由 x_offsety_offsetwidthheight 定义的区域内渲染。此区域不得落在默认图像之外;因此 x_offset 加上 width 不得大于 IHDR 宽度;同样,y_offset 加上 height 不得大于 IHDR 高度。

delay_numdelay_den 定义延迟分数的分子和分母;指示显示当前帧的时间,以秒为单位。如果分母为 0,则应将其视为 100(即 delay_num 指定 1/100 秒)。如果分子值为 0,解码器应尽快渲染下一帧,尽管查看器可能会施加合理的下限。它们被编码为双字节无符号整数。

帧时序应独立于每一帧的解码和显示所需时间,以便无论解码器实现性能如何,动画都能以相同的速率运行。

dispose_op 定义渲染此帧后要完成的帧区域处置类型;换句话说,它指定了在延迟结束时(在渲染下一帧之前)应如何更改输出缓冲区。它被编码为单字节无符号整数。

dispose_op 的有效值为:

0 APNG_DISPOSE_OP_NONE
1 APNG_DISPOSE_OP_BACKGROUND
2 APNG_DISPOSE_OP_PREVIOUS
APNG_DISPOSE_OP_NONE
渲染下一帧之前不对该帧进行任何处置;输出缓冲区的内容保持原样。
APNG_DISPOSE_OP_BACKGROUND
在渲染下一帧之前,将输出缓冲区的帧区域清除为完全透明的黑色。
APNG_DISPOSE_OP_PREVIOUS
在渲染下一帧之前,将输出缓冲区的帧区域还原为先前的内容。

如果第一个 fcTL 数据块使用的 dispose_opAPNG_DISPOSE_OP_PREVIOUS,则应将其视为 APNG_DISPOSE_OP_BACKGROUND

blend_op 指定是将帧 Alpha 混合到当前输出缓冲区内容中,还是将其完全替换输出缓冲区中的区域。它被编码为单字节无符号整数。

blend_op 的有效值为:

0 APNG_BLEND_OP_SOURCE
1 APNG_BLEND_OP_OVER

如果 blend_opAPNG_BLEND_OP_SOURCE,则帧的所有颜色分量(包括 Alpha)都会覆盖帧输出缓冲区区域的当前内容。如果 blend_opAPNG_BLEND_OP_OVER,则应根据其 Alpha 将帧合成到输出缓冲区上,使用 Alpha 通道处理中描述的简单 OVER 操作。注意,示例代码的第二个变体是适用的。

注意,对于第一帧,由于每次播放开始时都会清除输出缓冲区,因此两种混合模式在功能上是等效的。

对应于默认图像的 fcTL 数据块(如果存在)具有以下限制:

  • x_offsety_offset 字段必须为 0。
  • widthheight 字段必须等于 IHDR 数据块中对应的字段。

如前所述,每次播放开始时,输出缓冲区必须完全初始化为完全透明的黑色。这是为了确保动画的每次播放都是相同的。只要结果保证相同,解码器可以自由地避免显式清除步骤。例如,如果默认图像包含在动画中,并且使用 APNG_BLEND_OP_SOURCEblend_op,则不需要清除,因为整个输出缓冲区将被覆盖。

为了实现 Web 兼容性,鉴于此数据块的开发部署与将其合并到 PNG 规范之间的时间较长,此数据块名称被特殊定义为私有数据块。

11.3.6.3 fdAT 帧数据数据块

四字节数据块类型字段包含十六进制值

66 64 41 54

fdAT 数据块对于动画的作用与 IDAT 数据块对于静态图像的作用相同;fdAT 数据块集包含所有帧的图像数据(对于将静态图像作为第一帧的动画,则是第一帧之后的所有帧)。它包含

28 fdAT 数据块内容
名称 大小
序列号 (sequence_number) 4 字节
帧数据 (frame_data) n 字节

除第一帧外,每帧都需要至少一个 fdAT 数据块(如果该帧由 IDAT 数据块表示)。

每一帧的压缩数据流是该帧内所有 fdAT 数据块的 frame_data 字段按序列号升序连接的结果。

由于序列号的存在,fdAT 数据块 不能为零长度;但 frame_data 字段可以为零长度。解压缩后,数据流是完整 PNG 图像的像素数据,包括每行扫描线开头的过滤字节,类似于所有 IDAT 数据块的未压缩数据。它使用与静态图像相同的位深度、颜色类型、压缩方法、过滤方法、隔行扫描方法和调色板(如果有)。

每一帧都继承了文件第一个 IDAT 数据块之前的所有关键或辅助数据块指定的每个属性,宽度和高度除外,它们来自 fcTL 数据块。

如果存在 PNG pHYs 数据块,则 APNG 图像及其 x_offsety_offset 值必须与主图像以相同的方式缩放。从概念上讲,这种缩放是在将输出缓冲区映射到画布上时发生的。

为了实现 Web 兼容性,鉴于此数据块的开发部署与将其合并到 PNG 规范之间的时间较长,此数据块名称被特殊定义为私有数据块。

12. PNG 编码器

引言

本条款给出了对编码器行为的要求和建议。PNG 编码器应根据前述条款中规定的格式,从 PNG 图像生成 PNG 数据流。通常,遵循此处给出的附加建议将获得最佳结果。

12.1 编码器伽马处理

有关 伽马 问题的简要介绍,请参见 C. 伽马和色度

具备完全色彩管理能力的 PNG 编码器将执行比此处描述的更复杂的计算,并可能选择使用 iCCP 数据块。如果已知图像采样符合 sRGB 规范 [SRGB],强烈鼓励编码器写入 sRGB 数据块,而不进行额外的 伽马 处理。在这两种情况下,建议生成一个适当的 gAMA 数据块,供不识别 iCCPsRGB 数据块的 PNG 解码器使用。

PNG 编码器必须确定:

  1. gAMA 数据块中写入什么值;
  2. 如何将提供的图像采样转换为要写入 PNG 数据流的值。

写入 gAMA 数据块的值是导致 PNG 解码器以预期方式表现的值。参见 13.13 解码器伽马处理

要应用的转换取决于图像采样的性质及其精度。如果采样以浮点数或高精度整数形式(可能来自计算机图形渲染器)表示光强度,则编码器可能在将数据量化为整数值以包含在 PNG 数据流中之前执行 伽马编码(应用指数小于 1 的幂函数)。这会导致在给定的采样深度下产生更少的条带伪影,或者在保持相同的视觉质量的同时允许更小的采样。以 0 到 1 之间的浮点值表示的强度级别可以通过以下公式转换为数据流图像采样:

integer_sample = floor((2sampledepth-1) * intensityencoding_exponent + 0.5)

如果公式中的强度是预期的输出强度,则编码指数就是 gAMA 数据块中要使用的 伽马值

如果 PNG 编码器可用的强度是原始场景强度,则可能需要进行另一次转换。有时要求显示的图像比原始源图像具有更高的对比度。这对应于从原始场景到显示输出的端到端 传递函数,其指数大于 1。在这种情况下:

gamma = encoding_exponent/end_to_end_exponent

如果不知道原始图像拍摄或计算的条件是否需要这种对比度变化,可以假定显示强度与原始场景强度成正比,即端到端指数为 1,因此:

gamma = encoding_exponent

如果图像仅写入数据流,编码器可以自由选择编码指数。选择导致 gAMA 数据块中的 伽马值为 1/2.2 的值通常是一个合理的选择,因为它最大限度地减少了在典型视频监视器上显示的 PNG 解码器的工作。

一些图像渲染器可能同时将图像写入 PNG 数据流并将其显示在屏幕上。显示的像素应针对所使用的显示系统和观看条件进行 伽马 校正,以便用户看到预期场景的正确表示。

如果渲染器想要将显示的采样值写入 PNG 数据流,避免对数据流进行单独的 伽马编码步骤,渲染器应通过幂函数近似显示系统的 传递函数,并将指数的倒数写入 gAMA 数据块。这将允许 PNG 解码器再现源创建者在渲染时屏幕上显示的内容。

然而,渲染器计算适合显示设备的显示像素,并为数据存储和传输执行单独的 伽马编码,并安排 gAMA 数据块中具有更适合图像未来用途的值,这同样是合理的。

计算机图形渲染器通常不执行 伽马编码,而是使采样值直接与场景光强度成正比。如果 PNG 编码器接收到已经量化为整数值的采样值,则对其进行 伽马编码毫无意义;那只会导致进一步的信息丢失。编码器应直接将采样值写入 PNG 数据流。这并不意味着 gAMA 数据块应包含 1.0 的 伽马值,因为从场景强度到显示输出强度的预期端到端 传递函数并不一定是线性的。然而,预期的 伽马值可能离 1.0 不远。它可能取决于正在渲染的场景是日光场景还是室内场景等。

当采样值直接来自硬件时,原则上可以从硬件的 传递函数 和场景的照明条件推断出正确的 gAMA 值。在视频数字化仪(“图像采集卡”)的情况下,采样可能在 sRGB 色彩空间中,因为 sRGB 规范旨在与现代视频标准兼容。图像扫描仪的可预测性较差。它们的输出采样可能与输入光强度成正比,因为 CCD 传感器本身是线性的;或者扫描仪硬件可能已经应用了旨在补偿后续打印中点增益的幂函数(指数约为 0.57);或者扫描仪可能已经针对显示器上的显示对采样进行了校正。可能需要参考扫描仪手册或扫描校准目标以确定特定扫描仪的特征。应该记住,伽马 将采样与预期的显示输出联系起来,而不是与扫描仪输入联系起来。

数据流格式转换器通常不应尝试将提供的图像转换为不同的 伽马。数据应在不进行转换的情况下存储在 PNG 数据流中,并且应尽可能从源数据流中的信息推导出 伽马值。在数据流转换时改变 伽马 会导致所表示的强度级别集重新量化,从而引入额外的舍入误差,且收益甚微。直接从输入文件复制采样值到输出文件几乎总是更好的做法。

如果源数据流描述了图像的 伽马 特征,强烈鼓励数据流转换器写入 gAMA 数据块。某些数据流格式指定了显示指数(将图像采样映射到显示输出的函数指数,而不是相反方向)。如果源文件的 伽马值大于 1.0,它很可能是显示指数,则应使用此值的倒数作为 PNG 伽马值。如果源文件格式记录了图像采样与除显示输出以外的量之间的关系,那么推导 PNG 伽马值将比这更复杂。

如果 PNG 编码器或数据流转换器知道图像已经使用其 传递函数 可以通过指数为 display_exponent 的幂函数近似的显示系统令人满意地显示,则该图像可以被标记为具有 伽马值

gamma = 1/display_exponent

写入具有近似正确值的 gAMA 数据块,要比省略该数据块并强制 PNG 解码器猜测近似 伽马值更好。如果 PNG 编码器无法推断 伽马值,最好省略 gAMA 数据块。如果必须进行猜测,则应留给 PNG 解码器来完成。

伽马 不适用于 Alpha 采样;Alpha 总是以线性方式表示。

参见 13.13 解码器伽马处理

12.2 编码器颜色处理

有关颜色问题的参考,请参见 C. 伽马和色度

具备完全色彩管理能力的 PNG 编码器将执行比此处描述的更复杂的计算,并可能选择使用 iCCP 数据块。如果已知图像采样符合 sRGB 规范 [SRGB],强烈鼓励 PNG 编码器使用 sRGB 数据块。

如果编码器能够确定源显示器原色的色度,或者基于图像来源或运行它的硬件做出强有力的猜测,则强烈鼓励编码器输出 cHRM 数据块。如果这样做,也应写入 gAMA 数据块;如果缺少 gAMA 数据块,解码器无法对 cHRM 数据块做太多处理。

有许多关于原色和白点的建议和标准,其中一些与特定技术相关,例如 CCIR 709 标准 [ITU-R-BT.709] 和 SMPTE-C 标准 [SMPTE-170M]。

需要考虑三种情况:

  1. 编码器是生成系统的一部分;
  2. 源图像由相机或扫描仪捕获;
  3. PNG 数据流是通过从其他某种格式转换而生成的。

对于手绘或数字编辑的图像,必须确定在制作时是在什么显示器上观看的。许多图像编辑程序允许指定所使用的显示器类型。这通常是因为它们在内部使用某种与设备无关的空间进行工作。这些程序有足够的信息来编写有效的 cHRMgAMA 数据块,并强烈建议自动执行此操作。

如果编码器是作为执行全光谱渲染的计算机图像渲染器的一部分进行编译的,则应将用于从内部与设备无关的色彩空间转换为 RGB 的显示器值写入 cHRM 数据块。任何超出所选 RGB 设备色域的颜色都应映射到色域内;PNG 不存储超出色域的颜色。

如果计算机图像渲染器直接在与设备相关的 RGB 空间中进行计算,则不应写入 cHRM 数据块,除非场景描述和渲染参数已针对特定显示器进行了调整。在这种情况下,应使用该显示器的数据来构建 cHRM 数据块。

少数图像格式存储校准信息,这些信息可用于填充 cHRM 数据块。例如,TIFF 6.0 文件 [TIFF-6.0] 可以选择性地存储校准信息,如果存在该信息,则应将其用于构建 cHRM 数据块。

由近期视频设备创建的视频可能使用 CCIR 709 原色和 D65 白点 [ITU-R-BT.709],这些数据在 29 中给出。

29 CCIR 709 原色和 D65 白点
  R G B 白点
x 0.640 0.300 0.150 0.3127
y 0.330 0.600 0.060 0.3290

一种较旧但仍然非常流行的视频标准是 SMPTE-C [SMPTE-170M],在 30 中给出。

30 SMPTE-C 视频标准
  R G B 白点
x 0.630 0.310 0.155 0.3127
y 0.340 0.595 0.070 0.3290

建议数据流格式转换器尝试将提供的图像转换为不同的 RGB 色彩空间。数据应在不进行转换的情况下存储在 PNG 数据流中,如果已知源原色色度,则应将其记录下来。由于色域不匹配和舍入误差,在数据流转换时进行色彩空间转换是不明智的。与 伽马 转换一样,最好以无损方式存储数据,并在最终显示图像时至多进行一次转换。

参见 13.14 解码器颜色处理

12.3 Alpha 通道创建

Alpha 通道既可以看作是暂时隐藏图像透明部分的遮罩,也可以看作是构建非矩形图像的一种手段。在前一种情况下,应保留完全透明像素的颜色值以备将来使用。在后一种情况下,透明像素不携带任何有用数据,仅用于填充 PNG 所需的矩形图像区域。在这种情况下,为了获得最佳压缩效果,所有完全透明的像素都应分配相同的颜色值。

图像作者应牢记解码器可能不会完全支持透明度控制的可能性(参见 13.16 Alpha 通道处理)。因此,在可行的情况下,分配给透明像素的颜色应为合理的背景颜色。

对于不需要完整 Alpha 通道,或无法承担压缩效率损失的应用,还可以使用 tRNS 透明度数据块。

如果图像具有已知的背景颜色,则应将此颜色写入 bKGD 数据块。即使是忽略透明度的解码器,也可以使用 bKGD 颜色来填充未使用的屏幕区域。

如果原始图像具有预乘(也称为“关联”)Alpha 数据,则可以通过将每个采样值除以对应的 Alpha 值,然后乘以图像位深度的最大值,并舍入到最接近的整数,将其转换为 PNG 的非预乘格式。在有效的预乘数据中,采样值绝不会超过其对应的 Alpha 值,因此除法结果应始终在 0 到 1 的范围内。如果 Alpha 值为零,则输出黑色(零)。

12.4 采样深度缩放

当编码 PNG 中无法直接表示的采样深度的输入采样时,编码器应将采样向上缩放到 PNG 允许的采样深度。最精确的缩放方法是线性方程

output = floor((input * MAXOUTSAMPLE / MAXINSAMPLE) + 0.5)

其中输入采样的范围从 0 到 MAXINSAMPLE,输出范围从 0 到 MAXOUTSAMPLE(即 2sampledepth-1)。

“左位复制”(left bit replication)是线性缩放方法的一种近似方法,它是将有效位移位到最高位开始,并将最高位重复填充到空位中。这种方法通常比线性缩放计算更快。

假设 5 位采样被缩放到 8 位。如果源采样值为 27(在 0-31 范围内),则原始位为

4 3 2 1 0
---------
1 1 0 1 1

左位复制给出的值为 222

7 6 5 4 3  2 1 0
----------------
1 1 0 1 1  1 1 0
|=======|  |===|
    |      Leftmost Bits Repeated to Fill Open Bits
    |
Original Bits

这与线性方程计算出的值相匹配。左位复制通常给出与线性缩放相同的值,且误差从不超过 1。

一种准确度明显较低的近似方法是简单地将输入值左移并用零填充低位。此方案无法精确重现白色,因为它不会生成全 1 的最大值;其净效果是使图像略微变暗。一般不建议使用此方法,但它确实具有提高压缩效果的作用,特别是在处理大于 8 位采样深度时。由于零填充缩放在高采样深度时引入的相对误差较小,一些编码器可能会选择使用它。但是,零填充不得用于 Alpha 通道数据,因为许多解码器会将全零和全一的 Alpha 值视为特殊情况。在缩放数据中精确表示这两个值非常重要。

当编码器写入 sBIT 数据块时,要求以存储采样的高位与原始数据匹配的方式进行缩放。也就是说,如果 sBIT 数据块指定了 S 的采样深度,则存储数据的最高 S 位必须与原始 S 位数据值一致。这允许解码器通过右移来恢复原始数据。增加的低位不受限制。上述所有缩放方法均符合此限制。

在向上缩放源 图像数据 时,建议一致地填充所有采样的低位;也就是说,相同的源值应在任何像素位置生成相同的采样值。这通过减少不同采样值的数量来提高压缩率。这不是强制性要求,一些编码器可能选择不遵循它。例如,编码器可能会对低位进行抖动处理,以提高显示的图像质量,但代价是增加文件大小。

在某些应用中,原始源数据的范围可能不是 2 的幂。线性缩放方程在这种情况下仍然有效,尽管移位方法不适用。建议不要为此类图像写入 sBIT 数据块,因为 sBIT 暗示原始数据范围恰好是 0..2S-1。

12.5 建议调色板

建议调色板可以作为 sPLT 数据块出现在任何 PNG 数据流中,或者作为 PLTE 数据块出现在 真彩色 PNG 数据流中。无论哪种情况,建议调色板都不是 图像数据 的核心部分,但它可用于在索引色显示硬件上呈现图像。建议调色板对于在 真彩色 硬件上运行的查看器没有任何意义。

当使用 sPLT 数据块提供建议调色板时,建议编码器使用频率字段来指示调色板条目的相对重要性,而不是将它们全部留为零(表示未定义)。频率值最容易计算为“最近邻”计数,即如果不应用抖动,每个 RGBA 调色板条目的近似使用情况。(这些计数通常作为开发建议调色板的结果“免费”获得。)因为建议调色板包含透明度信息,所以应针对未合成的图像进行计算。

即使对于索引色图像,sPLT 也可用于为无法显示 PLTE 数据块中存在的所有颜色的查看器定义替代的简化调色板。如果 PLTE 数据块在 颜色类型 6 的图像中出现而没有 bKGD 数据块,则计算调色板的情况未指定。

一种在 真彩色 PNG 数据流中包含建议调色板的较旧方法是使用 PLTE 数据块。如果使用此方法,直方图(频率)应出现在单独的 hIST 数据块中。PLTE 数据块不包含透明度信息。因此,对于 颜色类型 6(带 Alpha 的真彩色)的图像,建议出现 bKGD 数据块,并且调色板和直方图应参照在指定背景颜色上合成后的图像进行计算。此定义对于确保为具有分数 Alpha 值的像素生成有用的调色板条目是必要的。生成的调色板可能仅对在相同背景颜色上呈现图像的查看器有用。建议 PNG 编辑器 如果更改或删除了 颜色类型 6 图像中的 bKGD 数据块,则删除或重新计算调色板。

对于 颜色类型 2(真彩色)的图像,建议 PLTEhIST 数据块仅参照 RGB 数据计算,忽略任何透明颜色规范。如果数据流使用透明度(具有 tRNS 数据块),查看器可以轻松调整生成的调色板以用于其预期的背景颜色(参见 13.17 直方图和建议调色板的使用)。

为了提供建议调色板,sPLT 数据块在以下方面比 PLTE 数据块更灵活

  1. 使用 sPLT 可以提供多个建议调色板。PNG 解码器可以根据名称或条目数量选择合适的调色板。
  2. 颜色类型 6(带 Alpha 通道的真彩色)的 PNG 数据流中,PLTE 数据块表示已针对 bKGD 颜色合成的调色板,因此仅对在该背景颜色上显示有用。sPLT 数据块提供未合成的调色板,这对于在 PNG 解码器选择的背景上显示很有用。
  3. 由于 sPLT 数据块是一个辅助数据块,PNG 编辑器 可以添加或修改建议调色板,而无需被迫丢弃未知的“不安全复制”数据块。
  4. 尽管 sPLT 数据块允许用于 颜色类型 0、3 和 4(灰度索引色)的 PNG 数据流中,但在这些情况下,PLTE 数据块不能用于提供简化调色板。
  5. sPLT 数据块中可以出现超过 256 个条目。

使用 sPLT 数据块的 PNG 编码器也可以选择编写一个由 PLTEhIST 数据块表示的建议调色板,以便与不识别 sPLT 数据块的解码器兼容。

12.6 隔行扫描

本规范定义了两种隔行扫描方法,其中一种是不隔行扫描。隔行扫描为解码器渐进式显示图像提供了便利的基础,如 13.10 隔行扫描和渐进式显示 中所述。

12.7 过滤选择

对于 颜色类型 3(索引色)的图像,过滤类型 0(无)通常是最有效的。具有 256 色或更少颜色的彩色图像几乎总是应该以 索引色 格式存储;真彩色 格式可能会大得多。

对于位深度小于 8 的图像,也建议使用过滤类型 0。对于低位深度的灰度图像,在极少数情况下,先将图像扩展为 8 位表示,然后再应用过滤可能会获得更好的压缩效果。

对于 真彩色灰度 图像,五种过滤器中的任何一种都可能是最有效的。如果编码器使用固定过滤器,Paeth 过滤器类型最有可能是最好的。

为了获得 真彩色灰度 图像的最佳压缩效果,并且如果压缩效率重于压缩速度,推荐的方法是自适应过滤,即为每一行扫描线选择一种过滤器类型。每个独特的图像将具有一组对其表现最好的不同过滤器。编码器可以尝试每种过滤器组合以找到最适合特定图像的压缩方式。但是,当穷举搜索不可接受时,以下是一些可能表现良好的通用启发式方法:使用所有五种过滤器计算输出扫描线,并选择给出输出绝对值之和最小的过滤器。(在此测试中,将输出字节视为带符号的差值。)这种方法通常优于任何单一的固定过滤器类型选择。

根据这些建议进行的过滤在与本规范定义的两种隔行扫描方法结合使用时非常有效。

12.8 压缩

编码器可以根据需要将压缩数据流划分为 IDAT 数据块。(允许多个 IDAT 数据块,以便编码器可以在固定数量的内存中工作;通常数据块大小将对应于编码器的缓冲区大小。)每个 IDAT 数据块仅包含一个数据字节的 PNG 数据流是有效的,尽管非常浪费空间。(零长度 IDAT 数据块也是有效的,尽管更浪费。)

12.9 文本数据块处理

每个文本数据块必须提供一个非空的关键字。如果没有更好的文本描述,可以使用通用关键字“Comment”。如果使用用户提供的关键字,编码器应检查它是否符合关键字的限制。

iTXt 数据块使用 Unicode 的 UTF-8 编码,因此可以存储任何语言的文本。tEXtzTXt 数据块使用 Latin-1 (ISO 8859-1) 字符编码,这限制了在这些数据块中可以使用的字符范围。编码器应优先使用 iTXt 而非 tEXtzTXt 数据块,以便在不丢失数据的情况下允许更广泛的字符集。编码器在存储文本时,必须将使用本地 旧版字符编码 的字符转换为适当的编码。

创建 iTXt 数据块时,编码器应遵循 编码标准 中的 UTF-8 编码

编码器应劝阻创建单行长度超过 79 个 Unicode 码点 的文本,以方便阅读。建议小于 1024 字节的文本项应使用未压缩的文本数据块输出。建议基础标题和作者关键字应使用未压缩的文本数据块输出。将大型文本数据块放置在 图像数据 之后(IDAT 数据块之后)可以在某些情况下加快图像显示,因为解码器会先解码 图像数据。建议小型文本数据块(例如图像标题)出现在 IDAT 数据块之前。

12.10 分块

12.10.1 私有数据块的使用

编码器 可以 使用私有数据块来携带不需要被其他应用程序理解的信息。

12.10.2 非保留字段值的使用

编码器 可以 将非保留字段值用于实验或私有用途。

12.10.3 辅助数据块

所有辅助数据块都是可选的,编码器无需编写它们。但是,鼓励编码器在信息可用时编写标准的辅助数据块。

13. PNG 解码器和查看器

引言

本条款给出了一些关于 PNG 解码器行为和查看器行为的要求和建议。查看器向用户呈现解码后的 PNG 图像。由于查看器和解码器行为密切相关,此处将解码器和查看器一并处理。对 PNG 解码器的唯一绝对要求是它必须成功读取任何符合前述章节中指定格式的数据流。然而,遵循以下额外建议通常会获得最佳结果。

PNG 解码器必须支持本国际标准中明确定义的所有位深度、颜色类型、压缩方法、过滤方法 和隔行扫描方法的有效组合。

13.1 错误处理

PNG 数据流中的错误分为两类:传输错误和语法错误(参见 4.10 错误处理)。

传输错误的示例包括以“文本”或“ascii”模式传输,其中字节代码 13 和/或 10 可能会在整个数据流中被添加、删除或转换;意外终止,其中数据流被截断;或者存储设备上的物理错误,其中一个或多个块(通常每个 512 字节)会有乱码或随机值。语法错误的一些示例包括行过滤器的无效值、无效的压缩方法、无效的数据块长度、索引图像中第一个 IDAT 数据块之前缺少 PLTE 数据块,或者存在多个 gAMA 数据块。PNG 解码器应按以下方式处理错误

  1. 尽早使用 PNG 签名字节和每个数据块上的 CRC 检测错误。解码器应验证 PNG 签名的所有八个字节是否正确。如果接下来的八个字节以具有正确数据块长度的 IHDR 数据块开头,解码器可以对数据流的完整性有额外的信心。CRC 应在处理数据块数据之前进行检查。有时这不切实际,例如当流式 PNG 解码器正在处理大型 IDAT 数据块时。在这种情况下,应在到达数据块末尾时检查 CRC
  2. 如果可能,从错误中恢复;否则优雅地失败。对图像处理影响极小或没有影响的错误可以忽略,而那些影响关键数据的错误应以适合应用程序的方式处理。
  3. 提供描述错误的有用消息,包括可恢复的错误。

三类 PNG 数据块与此哲学相关。出于此分类的目的,“未知数据块”是指其类型对解码器作者真正未知的数据块,或者作者选择将其视为未知的数据块,因为对该数据块类型的默认处理对于程序的目的来说已经足够。其他数据块称为“已知数据块”。基于此定义,三类数据块如下

  1. 已知数据块,必然包括本规范中定义的所有关键数据块(IHDRPLTEIDATIEND
  2. 未知关键数据块(数据块类型第一个字节的第 5 位为 0)
  3. 未知辅助数据块(数据块类型第一个字节的第 5 位为 1)

有关数据块命名约定的描述,请参见 5.4 数据块命名约定

PNG 数据块类型被标记为“关键”或“辅助”,取决于这些数据块对于提取可查看图像是否至关重要(如 IHDRPLTEIDAT),还是对于理解数据流结构至关重要(如 IEND)。这是一种特定类型的关键性,并不一定与每个可设想的解码器相关。例如,其唯一目的是提取文本注释(例如版权信息)的程序不需要可查看的图像,但应该 正确解码 UTF-8。另一个解码器可能认为 tRNSgAMA 数据块对其正常执行至关重要。

语法错误总是涉及已知数据块,因为未知数据块中的语法错误无法被检测到。PNG 解码器必须根据其要求和情况确定语法错误是致命的(不可恢复)还是非致命的。例如,大多数解码器可以忽略无效的 IEND 数据块;文本提取程序可以忽略 IDAT 的缺失;图像查看器无法从索引图像中的空 PLTE 数据块中恢复,但它可以忽略 真彩色 图像中无效的 PLTE 数据块;提取 Alpha 通道的程序可以忽略无效的 gAMA 数据块,但可能认为存在两个 tRNS 数据块是致命错误。除语法错误以外的异常情况应按以下方式处理

  1. 遇到未知的辅助数据块绝不是错误。该数据块可以简单地被忽略。
  2. 对于任何试图从数据流中提取图像的解码器,遇到未知关键数据块都是致命条件。忽略关键数据块的解码器无法知道它提取的图像是否是编码器预期的那个。
  3. PNG 签名不匹配、CRC 不匹配或意外的流结束表示数据流已损坏,并可被视为致命错误。解码器可以尝试从数据流中挽救一些东西,但损坏的程度将是未知的。

当发生致命条件时,解码器应立即失败,在适当的情况下向用户发出错误信号,并可选择继续显示用户已经可见的任何 图像数据(即“优雅地失败”)。整个应用程序无需终止。

当发生非致命错误时,解码器应在适当的情况下向用户发出警告信号,从错误中恢复,并继续正常处理。

解码索引色 PNG 时,如果遇到超出范围的索引,解码器在处理此错误的方式上历来有所不同。将像素显示为不透明黑色是一种常见的错误恢复策略,现在本规范对此有要求。旧实现会有所不同,因此编码器不得依赖此行为。

不计算 CRC 的解码器应将明显的语法错误解释为损坏的迹象(另请参见 13.2 错误检查)。

压缩数据块(IDATzTXtiTXtiCCP)中的错误可能导致缓冲区溢出。deflate 解压缩器的实现者应防范这种可能性。

APNG 旨在允许在读取整个 数据流 之前增量显示帧。这意味着某些错误可能直到动画进行到一半时才会被检测到。强烈建议解码器在遇到任何错误时丢弃所有后续帧,停止动画,并恢复显示静态图像。在动画开始前检测到错误的解码器应显示静态图像。如果适当,可以向用户显示错误消息。

解码器应将乱序的 APNG 数据块视为错误。支持 APNGPNG 编辑器 应使用序列号将它们恢复到正确的顺序。

13.2 错误检查

PNG 错误处理哲学在 13.1 错误处理 中进行了描述。

未知数据块类型应被视为错误,除非它是关键数据块。

通过查看所有四个字节是否在代码范围 41-5A 和 61-7A(十六进制)内,可以检查数据块类型的合理性;请注意,这仅对未识别的数据块类型进行即可。如果已知总数据流大小(来自文件系统信息、HTTP 协议等),也可以检查数据块长度的合理性。如果不检查 CRC,丢失/添加的数据字节或错误的数据块长度可能导致解码器失去同步,并将后续数据误解为数据块头。

对于已知长度的数据块(如 IHDR),解码器应将意外的数据块长度视为错误。本规范的未来扩展不会向现有数据块添加新字段;相反,将添加新的数据块类型来携带新信息。

应检查已知数据块字段中的意外值(例如 IHDR 数据块中的意外压缩方法)并将其视为错误。但是,建议仅在关键数据块中将意外字段值视为致命错误。辅助数据块中的意外值可以通过忽略整个数据块(就像它是一个未知数据块类型一样)来处理。(此建议假设数据块的 CRC 已被验证。在不检查 CRC 的解码器中,将任何意外值视为指示数据流已损坏更为安全。)

标准 PNG 图像应使用压缩方法 0 进行压缩。IHDR 数据块的压缩方法字段是为了可能的未来标准化或专有变体而提供的。解码器应检查此字节,如果它包含未识别的代码,则报告错误。有关详细信息,请参见 10. 压缩

13.3 安全考虑

PNG 数据流由一系列显式类型的数据块组成。其内容由规范定义的数据块实际上可能包含任何内容,包括恶意代码。IEND 数据块之后也可能存在数据,这些数据可能包含任何内容,包括恶意代码。由于解码 PNG 图像,在接收者的计算机上执行此类恶意代码的风险尚未可知。然而,恶意应用程序可能会将此类代码隐藏在看起来无辜的图像文件中,然后执行它。

目前无法指定与未来数据块类型相关的可能安全风险。在定义未来的公共数据块时将考虑安全问题。与未知或未实现的数据块类型相关的附加安全风险是不存在的,因为此类数据块将被忽略,或者最多被复制到另一个 PNG 数据流中。

iTXttEXtzTXt 数据块包含旨在作为纯文本显示的关键字和数据。iCCPsPLT 数据块包含旨在作为纯文本显示的关键字。如果解码器在显示此类文本时没有过滤掉控制字符,特别是 ESC(转义)字符,则某些系统或终端可能会出现不理想和不安全的行为。建议解码器过滤掉控制字符以避免此风险;参见 13.7 文本数据块处理

对于 eXIf 数据块,Exif 规范 [CIPA-DC-008] 没有包含明确要求标记“值偏移量”指针必须实际上指向文件内有效地址的规定。此要求仅是暗示的。(参见第 4.6.2 段,其中描述了 Exif IFD 结构。)无论如何,解码器都应准备好遇到无效指针并适当地处理它们。

每个数据块都以长度字段开头,这使得编写不受尝试溢出缓冲区的欺诈性数据块影响的解码器变得更加容易。每个数据块末尾的 CRC 为意外损坏的数据提供了强大的防御。PNG 签名字节提供了对常见文件传输错误的早期检测。

无法检查 CRC 的解码器可能会受到数据损坏的影响。此类损坏唯一可能的后果是图像内像素显示不正确。如果未检查 IHDR 数据块的 CRC 并且宽度或高度字段损坏,可能会发生更糟的事情。参见 13.2 错误检查

编写不良的解码器可能会受到缓冲区溢出的影响,因为数据块可能非常大,长达 231-1 字节。但编写良好的解码器将能毫无困难地处理大块数据。

13.4 隐私考虑

历史上,一些图像编辑工具通过仅将已修订区域的 Alpha 通道设置为零来执行修订,而没有同时删除实际的图像数据。仅仅依赖此类图像视觉外观的用户会面临隐私风险,因为实际的图像数据可以很容易地恢复。

类似地,一些图像编辑工具历史上通过重写 IHDR 中的宽度和高度而无需重新编码图像数据来执行剪裁,因此图像数据扩展到了新宽度和高度之外,并且可能被恢复。

具有 eXIf 数据块的图像可能包含自动包含的数据,例如摄影 GPS 坐标,如果用户不知道 PNG 图像包含此数据,这可能会成为隐私风险。(包含 EXIF 的其他图像格式,如 JPEG/JFIF,具有相同的隐私风险)。

13.5 分块

解码器应通过简单的四字节字面值比较来识别数据块类型;对数据块类型执行大小写转换是不正确的。遇到辅助位为 1 的未知数据块的解码器可以安全地忽略该数据块并继续显示图像。试图提取图像的解码器在遇到辅助位为 0(指示关键数据块)的未知数据块时,应向用户指出图像包含其无法安全解释的信息。

解码器应通过数值测试指定位来测试未知数据块类型的属性。测试字符是大写还是小写是低效的,如果使用了特定于语言环境的大小写定义,甚至是不正确的。

解码器不应将保留位设置为 1 标记为错误,因为 PNG 规范的某些未来版本可能会为此位定义含义。将设置了此位的数据块视为与其他未知数据块类型相同的方式处理已足够。

解码器不需要测试数据块类型的私有位,因为它没有功能意义,用于避免 W3C 定义的数据块与私有定义的数据块之间的冲突。

所有辅助数据块都是可选的;解码器可以忽略它们。但是,鼓励解码器在适当且可行的情况下解释这些数据块。

13.6 像素尺寸

非正方形像素可以表示(参见 11.3.4.3 pHYs 物理像素尺寸),但查看器不需要考虑它们;查看器可以将任何 PNG 数据流呈现为好像其像素是正方形一样。

当显示器的像素纵横比与 PNG 数据流中定义的物理像素尺寸的纵横比不同时,强烈鼓励查看器重新缩放图像以进行正确显示。

pHYs 数据块具有 0 的单位说明符(单位未知)时,解码器的行为可能取决于两个“每单位像素数”值的比率,但不应取决于它们的大小。例如,包含 (ppuX, ppuY, unit) = (2, 1, 0)pHYs 数据块等同于包含 (1000, 500, 0) 的数据块;两者同样有效地表明图像像素的高度是宽度的两倍。

查看器处理图像和显示器的像素纵横比之间差异的一种合理方法是水平或垂直扩展图像,但不要同时进行。比例因子可以使用以下浮点计算获得

image_ratio = pHYs_ppuY / pHYs_ppuX
display_ratio = display_ppuY / display_ppuX
scale_factor_X = max(1.0, image_ratio/display_ratio)
scale_factor_Y = max(1.0, display_ratio/image_ratio)

因为保持图像区域等其他方法也是合理的,而且允许忽略 pHYs 数据块,所以作者不应假设所有查看应用程序都会使用此缩放方法。

除了修正像素纵横比外,查看器可能有理由执行额外的水平和垂直缩放。例如,查看器可能希望缩小太大而无法适合显示器的图像,或者扩展发送到高分辨率打印机的图像,使其看起来与显示器上的大小相同。

13.7 文本数据块处理

如果实际可行,PNG 解码器应有一种方式向用户显示数据流中找到的所有 iTXttEXtzTXt 数据块。即使解码器不识别特定的文本关键字,用户也可能能够理解它。

处理 tEXtzTXt 数据块时,解码器可能会遇到非允许的字符。有些可以安全显示(例如 TAB、FF 和 CR,分别为十六进制 09、0C 和 0D),但其他字符,特别是 ESC 字符(十六进制 1B),可能会造成安全隐患(因为显示硬件或软件可能会采取意外的操作)。解码器不应尝试直接显示在 tEXtzTXt 数据块中遇到的任何非 Latin-1 字符(换行符和可能的 TAB、FF、CR 除外)。相反,它们应该被忽略或以可见符号(如“\nnn”)显示。参见 13.3 安全考虑

处理 iTXt 数据块时,解码器应遵循 编码标准 中的 UTF-8 解码

即使建议编码器将换行符表示为换行符(十六进制 0A),也建议解码器不要依赖于此;最好识别所有常见的换行组合(CR、LF 和 CR-LF)并将每个组合显示为单个换行符。TAB 可以扩展为到达 8 的列倍数所需的适当空格数。

在具有非 Latin-1 旧版字符编码 的系统上运行的解码器应重新映射字符代码,以便正确显示 Latin-1 字符。不支持的字符应替换为系统适当的替换字符(例如 U+FFFD 替换字符、U+003F 问号或 U+001A SUB)或映射到可见符号(例如“\nnn”)。仅当字符是解码系统上的可打印字符时才应显示。某些字节值可能会被解码系统解释为控制字符;为了安全起见,在此类系统上运行的解码器不应显示这些控制字符。

即使建议编码器避免创建超过 79 个字符的行,解码器也应准备好显示在换行符之间包含任意数量可打印字符的文本数据块。

13.8 解压

本规范中使用的压缩技术不需要在解压缩开始前获得整个压缩数据流。因此,显示可以在整个解压缩数据流可用之前开始。本规范未来版本中的任何通用压缩方法极不可能不具有此属性。

必须强调的是,IDAT 数据块边界没有语义意义,可以在压缩数据流中的任何点出现。图像数据 的结构(例如扫描线边界)与 deflate 块边界或 IDAT 数据块边界之间没有必需的相关性。完整的 图像数据 由存储在若干 IDAT 数据块中的单个 zlib 数据流表示;假设不止于此的解码器是不正确的。某些编码器实现可能会输出这些结构确实相关的相关数据流,但解码器不能依赖于此。

13.9 过滤

为了反转过滤器的效果,解码器可能需要使用同一行上前一个像素、上一行中当前像素正上方的像素以及上述像素左侧像素的解码值。这意味着解码器始终需要至少存储一行 图像数据。即使某些过滤器类型不引用上一条扫描线,解码器在解码每条扫描线时也需要存储它,因为下一条扫描线可能会使用引用它的过滤器类型。参见 7.3 过滤

13.10 隔行扫描和渐进式显示

解码器必须能够读取隔行扫描图像。如果参考图像包含少于 5 列或少于 5 行,某些过程将为空。编码器和解码器应正确处理这种情况。特别是,过滤器类型字节仅与非空扫描线相关联;空缩减图像中不存在过滤器类型字节。

在慢速传输链路上接收图像时,查看器可以通过渐进式显示隔行扫描图像来改善感知的性能。这意味着每接收到一个缩减图像,就会基于到目前为止接收到的数据显示完整图像的近似值。通过将每个接收到的像素扩展以填充覆盖接收到的像素下方和右侧尚未传输的像素位置的矩形,可以获得一种简单而悦目的效果。此过程可以通过以下 ISO C 代码进行描述 [ISO_9899]

/*
    variables declared and initialized elsewhere in the code:
        height, width
    functions or macros defined elsewhere in the code:
        visit(), min()
 */

int starting_row[7]  = { 0, 0, 4, 0, 2, 0, 1 };
int starting_col[7]  = { 0, 4, 0, 2, 0, 1, 0 };
int row_increment[7] = { 8, 8, 8, 4, 4, 2, 2 };
int col_increment[7] = { 8, 8, 4, 4, 2, 2, 1 };
int block_height[7]  = { 8, 8, 4, 4, 2, 2, 1 };
int block_width[7]   = { 8, 4, 4, 2, 2, 1, 1 };

int pass;
long row, col;

pass = 0;
while (pass < 7)
{
    row = starting_row[pass];
    while (row < height)
    {
        col = starting_col[pass];
        while (col < width)
        {
            visit(row, col,
                  min(block_height[pass], height - row),
                  min(block_width[pass], width - col));
            col = col + col_increment[pass];
        }
        row = row + row_increment[pass];
    }
    pass = pass + 1;
}

函数 visit(row,column,height,width) 获取下一个传输的像素,并使用像素指示的颜色绘制指定高度和宽度的矩形,其左上角位于指定的行和列。注意,行和列是从左上角的 0,0 开始测量的。

如果查看器正在将接收到的图像与背景图像合并,则只绘制接收到的像素位置(visit() 函数仅设置指定行和列处的像素,而不是整个矩形)可能更方便。随着新图像逐渐替换旧图像,这会产生“淡入”效果。此方法的一个优点是可以在每个像素被替换时进行适当的 Alpha 或透明度处理。如上所述绘制矩形将覆盖以后可能需要的背景图像像素,如果这些位置最终接收到的像素结果是完全或部分透明的。仅当背景图像没有存储在屏幕外的任何位置时,这才会成为问题。

13.11 真彩色图像处理

为了实现 PNG 通用互操作性的目标,解码器应接受所有类型的 PNG 图像:索引色真彩色灰度。在索引色显示硬件上运行的查看器需要能够将 真彩色 图像简化为索引色以供查看。此过程称为“颜色量化”。

颜色量化的一种简单、快速的方法是将图像简化为固定调色板。通常使用具有均匀颜色间距的调色板(“色立方体”)来最小化每像素的计算量。对于照片类图像,建议进行抖动处理以避免在平滑渐变中出现难看的轮廓;然而,抖动引入了可能令人反感的颗粒感。

通过使用专门为图像选择的调色板,渲染质量可以大幅提高,因为色立方体通常有许多在任何特定图像中未使用的条目。此方法需要更多的工作,首先是选择调色板,其次是将单个像素映射到最近的可用颜色。PNG 允许编码器提供建议调色板,但并非所有编码器都会这样做,并且建议调色板在任何情况下都可能不合适(它们可能颜色过多或过少)。因此,高质量的查看器将需要随时准备调色板选择例程。大的查找表通常是映射单个像素到调色板条目的最可行方式,并具有足够的速度。

颜色量化的实现非常多。PNG 示例实现 libpng (http://www.libpng.org/pub/png/libpng.html) 包含了用于此目的的代码。

13.12 采样深度重新缩放

解码器可能希望将 PNG 数据缩放到较小的采样深度(数据精度)以进行显示。例如,16 位数据将需要简化为 8 位深度,以便在大多数现代显示硬件上使用。将 8 位数据简化为 5 位深度也很常见。

最准确的缩放是通过以下线性方程实现的

output = floor((input * MAXOUTSAMPLE / MAXINSAMPLE) + 0.5)

其中

MAXINSAMPLE = (2sampledepth)-1
MAXOUTSAMPLE = (2desired_sampledepth)-1

一种准确度稍低的转换是通过简单地向右移动 (sampledepth - desired_sampledepth) 位来实现的。例如,要将 16 位采样简化为 8 位,可以丢弃低字节。在许多情况下,移位方法对于显示目的而言足够准确,而且它肯定快得多。(但是,如果正在进行 伽马 校正,则可以将采样重缩放合并到 伽马 校正查找表中,如 13.13 解码器伽马处理 中所说明的那样。)

如果解码器需要向上缩放采样(例如,如果 帧缓冲区 的采样深度比 PNG 图像大),它应使用 12.4 采样深度缩放 中描述的线性缩放或左位复制。

sBIT 数据块存在时,可以通过向右移动到 sBIT 指定的采样深度来恢复参考 图像数据。请注意,线性缩放不一定会重现原始数据,因为编码器不需要使用线性缩放来向上缩放数据。但是,编码器被要求使用一种保留高位的方法,因此移位总是有效的。这是移位被认为比线性缩放更准确的唯一情况。解码器无需关注 sBIT 数据块;存储的图像是 IHDR 数据块指示的采样深度的有效 PNG 数据流;然而,在使用 sBIT 在将原始采样缩放到适合显示之前恢复它们通常比忽略 sBIT 产生更准确的显示。

将像素值与 tRNS 数据块值进行比较以检测透明像素时,比较应精确执行。因此,透明像素检测应在降低采样精度之前完成。

13.13 解码器伽马处理

参见 C. 伽马和色度 以获取对 伽马 问题的简要介绍。

能够进行全色彩管理的查看器将执行比此处描述的更复杂的计算。

为了使图像显示程序产生正确的色调再现,有必要考虑采样与显示输出之间的关系,以及显示系统的 传递函数。这可以通过计算来完成

sample = integer_sample / (2sampledepth - 1.0)
display_output = sample1.0/gamma
display_input = inverse_display_transfer(display_output)
framebuf_sample = floor((display_input * MAX_FRAMEBUF_SAMPLE)+0.5)

其中 integer_sample 是数据流中的采样值,framebuf_sample 是写入 帧缓冲区 的值,MAX_FRAMEBUF_SAMPLE帧缓冲区 采样的最大值(8 位为 255,5 位为 31 等)。第一行将整数采样转换为归一化的浮点值(范围 0.0 到 1.0),第二行转换为与所需显示输出强度成比例的值,第三行考虑显示系统的 传递函数,第四行转换为整数 帧缓冲区 采样。零的任何正幂次幂均为零。

可以在第二行和第三行之间插入一个步骤来调整 display_output,以考虑实际观看条件与参考观看条件之间的差异。但是,这种调整需要考虑遮盖眩光、黑电平映射和色彩外观模型,所有这些都不能通过幂函数很好地近似。此处未描述此类计算。如果忽略观看条件,错误通常很小。

显示 传递函数 通常可以通过幂为 display_exponent 的幂函数来近似,在这种情况下,第二行和第三行可以合并为

display_input = sample1.0/(gamma * display_exponent) = sampledecoding_exponent

以便仅执行一次幂计算。对于彩色图像,整个计算分别针对 R、G 和 B 值进行。

伽马值 可以直接从 gAMA 数据块中获取。或者,应用程序可能希望允许用户通过影响 伽马值 来调整显示图像的外观。例如,用户可以手动设置一个默认值为 1.0 的参数 user_exponent,应用程序可以设置

gamma = gamma_from_file / user_exponent
decoding_exponent = 1.0 / (gamma * display_exponent)
   = user_exponent / (gamma_from_file * display_exponent)

用户会将 user_exponent 设置为大于 1 以调暗中间色调,或小于 1 以提亮它们。

包含零的 gAMA 数据块是无意义的,但可能是错误出现的。解码器应忽略它,编辑器可以丢弃它并向用户发出警告。

没有必要为每个像素执行超越数学计算。相反,可以计算出一个查找表,给出每个可能采样值的正确输出值。这对于图像(对于 8 位精度)仅需要 256 次计算,而不是每个像素 1 或 3 次计算。对于索引色图像,除非图像使用透明度并在不均匀的背景下显示,否则调色板的一次性校正已足够。

如果无法进行浮点计算,可以使用整数算术和预计算的对数表来计算 伽马 校正表。示例代码出现在 [PNG-EXTENSIONS] 中。

当传入图像具有未知的 伽马值gAMAsRGBiCCP 均不存在)时,独立图像查看器应选择一个可能的默认 伽马值,但如果结果证明太暗或太亮,则允许用户选择一个新的。默认的 伽马值 可能取决于有关图像的其他知识,例如它是来自互联网还是来自本地系统。为了保持一致性,HTML 等文档格式或 SVG 等矢量图形的查看器应以与处理其他未标记图像相同的方式处理具有未知 伽马值 的嵌入或链接 PNG 图像。

在实践中,通常很难确定应该使用什么值的显示指数。在没有内置 伽马 校正的系统中,显示指数完全由 CRT 决定。除非对所使用的特定 CRT 有详细的校准测量,否则应使用 2.2 的显示指数。

许多现代 帧缓冲区 具有用于执行 伽马 校正的查找表,在这些系统上,显示指数值应该是查找表和 CRT 组合的指数。可能无法从查看器应用程序内部查出查找表包含什么,在这种情况下,可能有必要要求用户提供显示系统的指数值。不幸的是,不同的制造商使用不同的方式来指定查找表中应该包含什么,因此对系统 伽马值 的解释是与系统相关的。

真实显示器的响应实际上比单个数字(显示指数)所能描述的要复杂得多。如果可以获得显示器光输出作为电压输入函数的实际测量值,则上述计算的第三行和第四行可以用这些测量值的查找表替换,以找到最接近给定所需亮度的实际 帧缓冲区 值。

13.14 解码器颜色处理

有关颜色问题的参考,请参见 C. 伽马和色度

在许多情况下,PNG 数据流中的 图像数据 将被视为与设备相关的 RGB 值并显示,无需修改(适当的 伽马 校正除外)。这提供了 PNG 图像最快的显示速度。但除非查看器使用与原始图像作者所使用的完全相同的显示硬件,否则颜色不会与原始作者看到的完全相同,特别是对于较暗或近中性的颜色。cHRM 数据块提供的信息允许比单独的 伽马 校正更接近的色彩匹配。

cHRM 数据可用于将 图像数据 从 RGB 转换为 XYZ,并由此进入感知线性色彩空间(如 CIE LAB)。颜色可以被分区以生成最佳调色板,因为 CIE LAB 中两种颜色之间的几何距离与这些颜色看起来的不同程度密切相关(这与 RGB 或 XYZ 空间不同)。生成的颜色调色板一旦转换回 RGB 色彩空间,就可以用于显示或写入 PLTE 数据块。

作为图像处理应用程序一部分的解码器也可以将 图像数据 转换为 CIE LAB 空间进行分析。

在色彩保真度至关重要的应用中(如产品设计、科学可视化、医学、建筑或广告),PNG 解码器可以将 图像数据 从源 RGB 转换为查看图像所用的显示器的显示 RGB 空间。这涉及计算从源 RGB 到 XYZ 的矩阵和从 XYZ 到显示 RGB 的矩阵,然后结合它们以产生整体转换。PNG 解码器负责实现色域映射。

在具有色彩管理系统 (CMS) 的平台上运行的解码器可以将 图像数据gAMAcHRM 值传递给 CMS 以进行显示或进一步处理。

提供彩色打印设施的 PNG 解码器可以使用 Level 2 PostScript 中的设施来指定已校准 RGB 空间或与设备无关的色彩空间(如 XYZ)中的 图像数据。这将比简单的 RGB 到 CMYK 转换提供更好的色彩保真度。PostScript 语言参考手册 [PostScript] 给出了示例。此类解码器负责实现源 RGB(在 cHRM 数据块中指定)与目标打印机之间的色域映射。然后,PostScript 解释器负责生成所需的颜色。

PNG 解码器可以使用 cHRM 数据来计算彩色图像的准确灰度表示。从 RGB 到灰度的转换仅仅是计算 XYZ 的 Y(亮度)分量,它是 R、G 和 B 值的加权和。权重取决于显示器类型,即 cHRM 数据块中的值。PNG 解码器可能希望对没有 cHRM 数据块的 PNG 数据流执行此操作。在这种情况下,合理的默认值将是 CCIR 709 原色 [ITU-R-BT.709]。除非 PNG 图像确实是针对此类显示器进行色彩平衡的,否则应使用原始 NTSC 原色。

13.15 背景颜色

bKGD 数据块给出的背景颜色通常用于填充图像周围未使用的屏幕空间,以及图像内的任何透明像素。(因此,即使图像不使用透明度,bKGD 也是有效且有用的。)如果没有 bKGD 数据块,查看器将需要决定合适的背景颜色。在没有其他信息可用时,8 位 sRGB 色彩空间中如 153 的中灰色将是一个合理的选择。透明的黑色或白色文本和深色阴影(很常见)在此背景下都将是可读的。

具有呈现图像特定背景的查看器(如 Web 浏览器)应忽略 bKGD 数据块,实际上用其首选背景颜色或背景图像覆盖 bKGD

bKGD 数据块给出的背景颜色不应被视为透明,即使它恰好与 tRNS 数据块给出的颜色匹配(或者在 索引色 图像的情况下,指代被 tRNS 数据块标记为透明的调色板索引)。否则,人们将不得不想象在“背景后面”有东西来进行合成。背景颜色要么用作背景,要么被忽略;它不是 PNG 图像和某些其他背景之间的中间层。

事实上,bKGDtRNS 数据块指定相同的颜色是很常见的,因为那样的话,如果不实现透明度处理的解码器将给出预期的显示,至少在没有部分透明像素存在时是这样。

13.16 Alpha 通道处理

Alpha 通道可用于将前景图像合成到背景图像上。PNG 数据流定义了前景图像和透明度遮罩,但不定义背景图像。PNG 解码器需要支持这种最通用的情况。预计大多数解码器将能够支持针对单个背景颜色的合成。

用于计算合成采样值的方程是

output = alpha * foreground + (1-alpha) * background

其中 Alpha 以及输入和输出采样值表示为 0 到 1 范围内的分数。此计算应使用强度采样(而不是 伽马 编码的采样)执行。对于彩色图像,计算分别针对 R、G 和 B 采样进行。

以下代码说明了将前景图像合成到背景图像的一般情况。它假设前景图像的原始像素数据可用于背景图像,并且输出到用于显示的 帧缓冲区。其他变体也是可能的;请参见代码下方的注释。该代码允许前景图像和背景图像的采样深度和 伽马值 均不相同,且不一定适合显示系统。在实践中,在未先检查的情况下,不应做出关于相等的假设。

此代码是 ISO C [ISO_9899],为方便在下面的注释中引用而添加了行号。

01  int foreground[4];  /* image pixel: R, G, B, A */
02  int background[3];  /* background pixel: R, G, B */
03  int fbpix[3];       /* frame buffer pixel */
04  int fg_maxsample;   /* foreground max sample */
05  int bg_maxsample;   /* background max sample */
06  int fb_maxsample;   /* frame buffer max sample */
07  int ialpha;
08  float alpha, compalpha;
09  float gamfg, linfg, gambg, linbg, comppix, gcvideo;

    /* Get max sample values in data and frame buffer */
10  fg_maxsample = (1 << fg_sample_depth) - 1;
11  bg_maxsample = (1 << bg_sample_depth) - 1;
12  fb_maxsample = (1 << frame_buffer_sample_depth) - 1;
    /*
     * Get integer version of alpha.
     * Check for opaque and transparent special cases;
     * no compositing needed if so.
     *
     * We show the whole gamma decode/correct process in
     * floating point, but it would more likely be done
     * with lookup tables.
     */
13  ialpha = foreground[3];

14  if (ialpha == 0) {
        /*
         * Foreground image is transparent here.
         * If the background image is already in the frame
         * buffer, there is nothing to do.
         */
15      ;
16  } else if (ialpha == fg_maxsample) {
        /*
         * Copy foreground pixel to frame buffer.
         */
17      for (i = 0; i < 3; i++) {
18          gamfg = (float) foreground[i] / fg_maxsample;
19          linfg = pow(gamfg, 1.0 / fg_gamma);
20          comppix = linfg;
21          gcvideo = pow(comppix, 1.0 / display_exponent);
22          fbpix[i] = (int) (gcvideo * fb_maxsample + 0.5);
23      }
24  } else {
        /*
         * Compositing is necessary.
         * Get floating-point alpha and its complement.
         * Note: alpha is always linear; gamma does not
         * affect it.
         */
25      alpha = (float) ialpha / fg_maxsample;
26      compalpha = 1.0 - alpha;

27      for (i = 0; i < 3; i++) {
            /*
             * Convert foreground and background to floating
             * point, then undo gamma encoding.
             */
28          gamfg = (float) foreground[i] / fg_maxsample;
29          linfg = pow(gamfg, 1.0 / fg_gamma);
30          gambg = (float) background[i] / bg_maxsample;
31          linbg = pow(gambg, 1.0 / bg_gamma);
            /*
             * Composite.
             */
32          comppix = linfg * alpha + linbg * compalpha;
            /*
             * Gamma correct for display.
             * Convert to integer frame buffer pixel.
             */
33          gcvideo = pow(comppix, 1.0 / display_exponent);
34          fbpix[i] = (int) (gcvideo * fb_maxsample + 0.5);
35      }
36  }

变体

  1. 如果输出是到另一个 PNG 数据流而不是 帧缓冲区,则应按照以下行更改第 21、22、33 和 34 行
    /*
     * Gamma encode for storage in output datastream.
     * Convert to integer sample value.
     */
    gamout = pow(comppix, outfile_gamma);
    outpix[i] = (int) (gamout * out_maxsample + 0.5);
    此外,当 alpha 为零时,必须处理背景像素,而不是简单地跳过。因此,第 15 行需要用第 17-23 行的副本替换,但处理的是背景像素值而不是前景像素值。
  2. 如果输出文件、前景文件和背景文件的采样深度完全相同,且三个伽马值也匹配,那么第 14-23 行的非合成代码将简化为:如果 alpha 为 1,则将输入文件的像素值复制到输出文件;如果 alpha 为 0,则将背景文件的像素值复制到输出文件。由于图像中绝大多数像素的 alpha 值通常要么为 0,要么为 1,这可以节省大量时间。对于大多数像素,不需要进行伽马计算。
  3. 当采样深度和伽马值完全匹配时,跳过伽马解码和编码(第 28-31 行,33-34 行)并仅使用伽马编码后的样本值执行第 32 行代码看起来很有吸引力。虽然这对图像质量的影响并不大,但如果像本文建议的那样将 alpha 值为 0 和 1 作为特殊情况处理,时间节省是非常有限的。
  4. 如果背景图像的原始像素值已不再可用,只剩下背景图像显示后留下的帧缓冲区像素,则第 30 和 31 行需要使用类似以下代码从帧缓冲区像素值中提取强度:
    /*
     * Convert frame buffer value into intensity sample.
     */
    gcvideo = (float) fbpix[i] / fb_maxsample;
    linbg = pow(gcvideo, display_exponent);
    然而,这可能会导致一些舍入误差,因此如果可能,最好保留原始的背景像素。
  5. 请注意,第 18-22 行执行的伽马计算与不存在 alpha 通道时执行的计算完全相同。如果无 alpha 情况是使用查找表处理的,则此处可以使用相同的查找表。第 28-31 行和 33-34 行也可以使用(不同的)查找表来完成。
  6. 可以使用整数运算代替浮点运算,前提是小心维护全程所需的精度。

注意:在浮点运算中,不需要进行溢出或下溢检查,因为输入采样值保证在 0 和 1 之间,且合成结果始终在输入值之间(含边界)。使用整数运算时,可能需要进行舍入误差分析以确保没有溢出或下溢。

在显示带有完整 alpha 通道的 PNG 图像时,能够将图像与某个背景(即使只是黑色)进行合成非常重要。忽略 alpha 通道会导致那些由关联 alpha 表示法转换而来的 PNG 图像看起来不正确。(当然,如果 alpha 通道是独立的透明度遮罩,则忽略 alpha 是一个有用的选项:它允许恢复图像中隐藏的部分。)

即使解码器没有实现真正的合成逻辑,处理只包含零和一 alpha 值的图像也很简单。(对于使用 tRNS 数据块的灰度真彩色 PNG 数据流,这一点是隐含成立的;对于索引色 PNG 数据流,检查 tRNS 数据块是否包含 0 和 255 以外的值很容易。)在这种简单情况下,透明像素被背景颜色替换,其他像素保持不变。

如果解码器仅具备此程度的透明度能力,它应该通过将所有非零 alpha 值视为完全不透明或通过抖动来处理完整的 alpha 通道。这两种方法对于从关联 alpha 格式转换而来的图像都不会产生很好的效果,但这总比什么都不做要好。将完整 alpha 抖动到二进制 alpha 非常类似于将灰度抖动到黑白,不同之处在于所有完全透明和完全不透明的像素在抖动过程中应保持不变。

13.17 直方图和建议调色板的使用

对于在索引色硬件上运行且试图显示真彩色图像,或者索引色图像的调色板对于帧缓冲区而言太大的查看器,编码器可能已在 sPLT 数据块中提供了一个或多个建议调色板。如果根据大小或名称发现其中一个合适,PNG 解码器可以使用该调色板。采样深度与解码器需求不同的建议调色板可以使用采样深度重缩放进行转换(参见 13.12 采样深度重缩放)。

当背景为纯色时,查看器应将图像和建议调色板与该颜色进行合成,然后将生成的图像量化为结果 RGB 调色板。当图像使用透明度且背景不是纯色时,通常没有建议调色板是有用的。

对于真彩色图像,建议调色板也可以在 PLTE 数据块中提供。如果图像有 tRNS 数据块且背景是纯色,查看器将需要调整建议调色板以适应其所需的背景颜色。为此,应将最接近 tRNS 颜色的调色板条目替换为所需的背景颜色;或者,如果查看器能够处理比 PLTE 条目更多的颜色,也可以为背景颜色添加一个调色板条目。

对于颜色类型 6(带 alpha 的真彩色)的图像,任何 PLTE 数据块都应设计用于在由 bKGD 数据块指定的颜色背景上显示图像。如果查看器打算使用不同的背景,或者缺少 bKGD 数据块,则可能应该忽略该调色板。查看器可以使用建议调色板在与预期不同的背景上进行显示,但结果可能不会太好。

如果查看器在比纯色背景更复杂的背景上呈现透明真彩色图像,建议调色板不太可能是合成图像的最佳选择。在这种情况下,最好对真彩色 PNG 图像和背景图像执行真彩色合成步骤,然后对生成的图像进行颜色量化。

真彩色 PNG 数据流中,如果 PLTEsPLT 数据块同时出现,PNG 解码器可以从中选择,同时牢记上述不同的透明度语义。

当查看器无法提供 PNG 数据流中调色板所使用的颜色数量时,sPLThIST 数据块中的频率信息非常有用。如果查看器仅短缺少量颜色,通常只需从调色板中删除使用最少的颜色即可。若要大幅减少颜色数量,最好选择全新的代表颜色,而不是尝试使用现有调色板的子集。这相当于执行一次新的颜色量化步骤;然而,可以使用现有的调色板和直方图作为输入数据,从而避免扫描 IDAT 数据块中的图像数据

如果没有提供建议调色板,解码器可以自行开发一个,代价是对 IDAT 数据块中的图像数据进行额外的扫描。或者,可以使用默认调色板(通常是颜色立方体)。

另请参见 12.5 建议调色板

14. 编辑器

14.1 附加数据块类型

建议作者在考虑引入新数据块类型之前,先查看本规范和 [PNG-EXTENSIONS] 中的现有数据块类型。预计在 [PNG-EXTENSIONS] 中的数据块类型支持程度将低于本规范中定义的类型。

14.2 PNG 编辑器的行为

PNG 编辑器的两个示例是:一个添加或修改文本数据块的程序,以及一个向真彩色 PNG 数据流添加建议调色板的程序。普通图像编辑器不是PNG 编辑器,因为它们通常在读取图像时丢弃所有未识别的信息。

为了允许将新数据块类型添加到 PNG,必须建立所有数据块类型的排序要求规则。否则,PNG 编辑器在遇到未知数据块时将不知道该怎么办。

示例:考虑一种假设的新辅助数据块类型,它是安全复制的,并且如果 PLTE 存在,则要求出现在 PLTE 之后。如果程序试图添加一个 PLTE 数据块且不识别该新数据块,它可能会将 PLTE 数据块插入错误的位置,即在新数据块之后。通过要求 PNG 编辑器丢弃所有未知数据块可以防止此类问题,但这是一种非常不受欢迎的解决方案。相反,PNG 要求辅助数据块不具有这样的排序限制。

为了防止此类问题并允许未来扩展,对 PNG 编辑器的行为和允许的数据块排序要求都设置了约束。安全复制位定义了在正在修改的数据流中处理未识别数据块的正确方式。

  1. 如果数据块的安全复制位为 1,则无论 PNG 编辑器是否识别该数据块类型,以及数据流修改的程度如何,该数据块均可被复制到修改后的 PNG 数据流中。
  2. 如果数据块的安全复制位为 0,则表明该数据块依赖于图像数据。如果程序对关键数据块进行了任何更改(包括添加、修改、删除或重新排序关键数据块),则未识别的不安全数据块不得复制到输出的 PNG 数据流中。(当然,如果程序确实识别该数据块,它可以选择输出一个适当修改后的版本。)
  3. 如果 PNG 编辑器仅添加、删除、修改或重新排序了辅助数据块,则始终被允许复制所有未识别的辅助数据块。这意味着辅助数据块不允许依赖于其他辅助数据块。
  4. PNG 编辑器在遇到未识别的关键数据块类型时应当终止,因为无法确定修改包含此类数据块的数据流是否会产生有效的数据流。(仅仅丢弃该数据块是不够的,因为它可能对其他数据块的解释有未知的隐含影响。)安全/不安全机制旨在与辅助数据块一起使用。对于关键数据块,安全复制位将始终为 0。

数据块排序的规则如下。

  1. 在复制未知不安全复制的辅助数据块时,PNG 编辑器不得相对于任何关键数据块移动该数据块。它可以相对于同一对关键数据块之间出现的其他辅助数据块自由地重新定位该数据块。(这是定义明确的,因为如果编辑器正在保留未知的、不安全复制的数据块,它不得添加、删除、修改或重新排序关键数据块。)
  2. 在复制未知安全复制的辅助数据块时,PNG 编辑器不得将该数据块从 IDAT 之前移动到 IDAT 之后,反之亦然。(这是定义明确的,因为 IDAT 始终存在。)允许任何其他重新排序。
  3. 在复制已知辅助数据块类型时,编辑器只需遵守该数据块类型存在的特定数据块排序规则。然而,它始终可以选择应用上述一般规则。

这些规则是以将数据块从输入数据流复制到输出数据流的方式表达的,但如果 PNG 数据流是在原地修改的,它们也以明显的方式适用。

另请参见 5.4 数据块命名约定

不更改图像数据PNG 编辑器不应更改 tIME 数据块。tEXtzTXtiTXt 数据块中的创建时间关键字可用于用户提供的时间。

14.3 数据块的顺序

14.3.1 关键数据块的顺序

关键数据块可能有任意的排序要求,因为 PNG 编辑器被要求在遇到未知关键数据块时终止。例如,IHDR 有具体的排序规则,即它必须始终首先出现。PNG 编辑器,或者实际上任何 PNG 写入程序,都必须了解并遵循其可以生成的任何关键数据块类型的排序规则。

14.3.2 辅助数据块的顺序

辅助数据块类型最严格的排序规则是:

  1. 不安全复制的数据块可能相对于关键数据块有排序要求。
  2. 安全复制的数据块可能相对于 IDAT 有排序要求。

任何特定辅助数据块类型的实际排序规则可能更宽松。请参见 5.6 数据块排序中标准辅助数据块类型的排序规则。

解码器不得对任何辅助数据块的定位做出超出数据块排序规则所规定的假设。特别是,假设特定的辅助数据块类型相对于其他辅助数据块有任何特定的定位是永远无效的。

示例:假设特定的私有辅助数据块紧接在 IEND 之前是不安全的。即使它总是由特定程序写在该位置,PNG 编辑器也可能在其之后插入了其他辅助数据块。但假设该数据块将保留在 IDATIEND 之间的某个位置是安全的。

15. 一致性

除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。

本文档中的关键字 MAYMUSTSHALLSHOULDSHOULD NOT 仅在以全大写形式出现时(如图所示),应按 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。

15.1 一致性

15.2 简介

15.2.1 目标

本条款涉及 PNG 数据流、PNG 编码器、PNG 解码器和 PNG 编辑器的一致性。

本条款规范的主要目标是:

  1. 通过消除本规范的任意子集或扩展来促进互操作性;
  2. 促进一致性测试开发中的统一性;
  3. 促进 PNG 编码器、解码器和编辑器之间结果的一致性;
  4. 促进自动化测试生成。

15.2.2 范围

一致性是针对 PNG 数据流以及 PNG 编码器、解码器和编辑器定义的。

本条款涉及 PNG 数据流和实现要求,包括 PNG 编码器、PNG 解码器和 PNG 编辑器允许的差异范围。本条款不直接涉及编码器、解码器或编辑器的环境、性能或资源要求。

本条款的范围仅限于 PNG 数据流公开交换的规则。

15.3 一致性条件

15.3.1 PNG 数据流的一致性

如果满足以下条件,PNG 数据流即符合本规范。

  1. PNG 数据流以 PNG 签名作为第一个内容(参见 5.2 PNG 签名)。
  2. 关于本国际标准中定义的数据块类型:
    • PNG 数据流将 IHDR 数据块作为其第一个数据块,紧跟在 PNG 签名之后;
    • PNG 数据流将 IEND 数据块作为其最后一个数据块。
  3. IEND 数据块之后不得有任何数据块或其他内容。
  4. 其中包含的所有数据块均匹配本规范中相应数据块类型的规范。PNG 数据流必须遵守本规范中定义的数据块类型之间的关系。
  5. PNG 数据流中的数据块序列遵守本国际标准中指定的排序关系。
  6. PNG 数据流中的所有字段值均遵守本规范中指定的关系,从而产生本规范中指定的结构。
  7. PNG 数据流中不出现本规范指定之外的数据块,也不出现未根据本规范定义的创建新数据块类型规则而定义的数据块。
  8. PNG 数据流是根据本国际标准的规则编码的。

15.3.2 PNG 编码器的一致性

如果 PNG 编码器满足以下条件,则其符合本规范。

  1. PNG 编码器生成的所有 PNG 数据流均为符合规范的 PNG 数据流。
  2. 在编码具有无法直接由 PNG 表示的采样深度的输入采样时,编码器会将采样向上缩放到 PNG 允许的下一个更高采样深度。数据缩放方式应确保高位与原始数据匹配。
  3. 在为任何方法或类型字段编码实验性或私有值定义时,应使用私有字段值

15.3.3 PNG 解码器的一致性

如果 PNG 解码器满足以下条件,则其符合本规范。

  1. 它能够读取任何符合本国际标准的 PNG 数据流,包括类型可能未被识别的公共和私有数据块。
  2. 它支持任何符合本国际标准的 PNG 数据流中的所有标准化关键数据块,以及所有标准化的压缩、过滤和交错方法和类型。
  3. 未知数据块类型的处理方式如5.4 数据块命名约定所述。除非是关键数据块,否则未知数据块类型被视为错误。
  4. 已知数据块字段中的意外值(例如,IHDR 数据块中的意外压缩方法)被视为错误。
  5. 所有类型的 PNG 图像(索引色、真彩色灰度带 alpha 的真彩色带 alpha 的灰度)均会被处理。例如,作为运行在索引色显示硬件上的查看器一部分的解码器,应将真彩色图像缩减为索引格式以进行查看。
  6. 如果解码器正在尝试提取图像,遇到辅助位为 0 的未知数据块会产生错误。
  7. 保留位置位被设置的数据块类型将被视为未知数据块类型。
  8. 支持 11.2.1 IHDR 图像头中定义的所有位深度和颜色类型的有效组合。
  9. 如果在 IHDR 数据块的位深度、颜色类型、压缩方法、过滤方法或交错方法字节中遇到未识别的值,将报告错误。
  10. 当在 tRNS 数据块中处理 16 位灰度真彩色数据时,会评估采样值的两个字节以确定像素是否透明。
  11. 当处理由压缩方法 0 压缩的图像时,解码器假设完整的图像数据是由存储在若干 IDAT 数据块中的单个压缩数据流所表示的,除此之外不做任何假设。
  12. 除了数据块排序规则所规定的假设外,不对任何辅助数据块的定位做任何假设。

15.3.4 PNG 编辑器的一致性

如果 PNG 编辑器满足以下条件,则其符合本规范。

  1. 它符合 PNG 编码器的要求。
  2. 它符合 PNG 解码器的要求。
  3. 它能够编码其解码的所有数据块。
  4. 它保留了 5.6 数据块排序中规则范围内呈现的数据块顺序。
  5. 它正确处理安全复制位信息,并在安全复制规则允许的情况下保留未知数据块。
  6. 除非用户明确允许有损操作或编辑器发出警告,否则它必须保留重建参考图像所需的所有信息,但如果 alpha 通道仅包含零和最大值,则不需要保留其采样深度。允许在索引色数据流中进行更改颜色类型或重新排列调色板等操作,前提是新的数据流无损地表示相同的参考图像。

A. 互联网媒体类型

A.1 image/png

这更新了现有的 image/png 互联网媒体类型,属于 image 顶级类型。本附录符合 BCP 13W3CRegMedia

媒体类型名称
image
媒体子类型名称
png
必需参数
可选参数
编码注意事项
二进制:
安全考虑

PNG 文档由一组明确类型化的“数据块”集合组成。对于 PNG 规范中定义的每种数据块类型(gIFx 除外),与这些数据块相关联的唯一作用是导致图像在接收方的显示器或打印机上呈现。

gIFx 数据块类型用于封装应用程序扩展数据,对该数据的使用可能会带来安全风险,尽管目前尚无已知风险。同样,无法评估与未来数据块类型相关的安全风险,特别是未注册的数据块。然而,PNG 工作组的意图是不允许包含“可执行”数据的数据块成为注册数据块。

文本数据块 tEXtiTXTzTXt 包含可以以注释等形式显示的数据。一些操作系统或终端可能允许显示带有嵌入控制字符的文本数据,以执行诸如重新映射键、创建文件等操作。因此,本规范建议在直接显示之前对文本数据块进行控制字符过滤。

PNG 格式专门设计用于促进文件传输错误的早期检测,并利用循环冗余校验来确保其数据块中所含数据的完整性。

互操作性考虑
全程使用网络字节序。
已发布规范
可移植网络图形 (PNG) 规范, https://w3org.cn/TR/PNG/
使用此媒体的应用程序
PNG 被广泛应用于所有 Web 浏览器、图像查看器和图像创作工具中
片段标识符注意事项
不适用
使用限制
不适用
临时注册?(仅限标准树)
No
附加信息
此类型的已弃用别名
不适用
幻数
89 50 4E 47 0D 0A 1A 0A
文件扩展名
.png
Macintosh 文件类型代码
PNGf
对象标识符
不适用
一般性评论

此注册更新了之前的注册

  1. 旧注册指向一个已过期的互联网草案。此更新后的注册指向一份 W3C 推荐标准。
  2. 旧的联系人已遗憾离世。新的联系电子邮件是 PNG 工作组的公共存档 W3C 邮件列表。
  3. 变更控制方为 W3C
更多信息联系人
名称
PNG 工作组
Email
public-png@w3.org
预期用途
通用
作者/变更控制者
W3C

A.2 image/apng

本附录符合 BCP 13W3CRegMedia

媒体类型名称
image
媒体子类型名称
apng
必需参数
不适用
可选参数
不适用
编码注意事项
二进制:
安全考虑

APNG 文档由一组明确类型化的“数据块”集合组成。对于 PNG 规范中定义的每种数据块类型(gIFx 除外),与这些数据块相关联的唯一作用是导致动画图像在接收方的显示器上呈现。

gIFx 数据块类型用于封装应用程序扩展数据,对该数据的使用可能会带来安全风险,尽管目前尚无已知风险。同样,无法评估与未来数据块类型相关的安全风险,特别是未注册的数据块。然而,PNG 工作组的意图是不允许包含“可执行”数据的数据块成为注册数据块。

文本数据块 tEXtiTXtzTXt 包含可以以注释等形式显示的数据。一些操作系统或终端可能允许显示带有嵌入控制字符的文本数据,以执行诸如重新映射键、创建文件等操作。因此,本规范建议在直接显示之前对文本数据块进行控制字符过滤。

PNG 格式专门设计用于促进文件传输错误的早期检测,并利用循环冗余校验来确保其数据块中所含数据的完整性。

如果有人创建了一个包含无关静态图像和动画图像数据块的 APNG 文件,使用不支持 APNG 格式的工具的人将只能看到静态图像,而不会意识到额外内容的存在。这可能会被用于例如绕过审核。

互操作性考虑
已发布规范
可移植网络图形 (PNG) 规范, https://w3org.cn/TR/png/
使用此媒体的应用程序
动画 PNG (APNG) 被广泛应用于所有 Web 浏览器,并日益普及于图像查看器、动画和图像创作工具中
片段标识符注意事项
不适用
使用限制
不适用
临时注册?(仅限标准树)
No
附加信息
此类型的已弃用别名
image/vnd.mozilla.apng
幻数
89 50 4E 47 0D 0A 1A 0A
文件扩展名
.apng
对象标识符
不适用
一般性评论

image/apng 自 2015 年以来已在广泛、未注册的使用中。动画 PNG 直到 2022 年才成为官方 PNG 规范的一部分。此注册加上 PNG 规范(第三版)将官方文档与已经广泛部署的现实相统一。

更多信息联系人
名称
PNG 工作组
Email
public-png@w3.org
预期用途
通用
作者/变更控制者
W3C

B. 私有数据块类型指南

本节是非规范性的。

以下规定了私有数据块定义的准则:

  1. 不要定义重新定义现有数据块含义或更改现有标准化数据块解释的新数据块,例如,不要添加一个新数据块来说明 RGB 和 alpha 值实际上意味着 CMYK。
  2. 最大限度地减少私有数据块的使用,以帮助可移植性。
  3. 避免定义依赖于完整数据流内容的数据块。如果必须定义此类数据块,请将它们设为关键数据块。
  4. 对于可用 Latin-1 表示的文本信息,避免定义新的数据块类型。使用带有合适关键字的 tEXtzTXt 数据块来标识信息的类型。对于不可用 Latin-1 表示但可用 UTF-8 表示的文本信息,请使用带有合适关键字的 iTXt 数据块。
  5. 将相互依赖的辅助信息分组到一个单独的数据块中。这避免了引入数据块排序关系的必要性。
  6. 避免定义私有关键数据块。

C. 伽马和色度

本节是非规范性的。

伽马值是一个数值参数,用于描述图像采集和再现中遇到的某些非线性传递函数的近似值。伽马值是幂律函数中的指数。例如,函数:

强度 = (电压 + 常数)指数

被用于模拟 CRT 显示器的非线性。通常假设(如本国际标准中那样)该常数为零。

就本规范而言,考虑通用图像管线中可能出现非线性传递函数的五个位置是方便的,这些位置可以用幂律来建模。与每个位置相关的特征指数被赋予了一个特定的名称。

input_exponent 图像传感器的指数。
encoding_exponent 由写入数据流的流程或设备执行的任何传递函数的指数。
decoding_exponent 由读取图像数据流的软件执行的任何传递函数的指数。
LUT_exponent 帧缓冲区和显示设备之间应用的传递函数的指数(通常是通过查找表应用的)。
output_exponent 显示设备的指数。对于 CRT,这通常是一个接近 2.2 的值。

定义一些描述某些复合传递函数或阶段组合的额外实体是方便的。

display_exponent 帧缓冲区和显示设备的显示表面之间应用的传递函数的指数。
display_exponent = LUT_exponent * output_exponent
伽马函数 (gamma) 将显示输出强度映射到 PNG 数据流中采样的函数指数。
gamma = 1.0 / (decoding_exponent * display_exponent)
end_to_end_exponent 将图像传感器输入强度映射到显示输出强度的函数指数。这通常是 1.0 到 1.5 范围内的值。

PNG gAMA 数据块用于记录伽马值。解码器可以使用此信息以及关于显示环境的额外信息,以实现或近似所需的显示输出。

关于此主题的额外信息可在 [GAMMA-FAQ] 中找到。

关于颜色空间对图像编码影响的额外信息可在 [Kasson] 和 [Hill] 中找到。

关于色度和颜色空间的背景信息可在 [COLOR-FAQ] 中找到。

D. 示例 CRC 实现

以下示例代码(信息性)代表了 PNG 数据块中采用的 CRC(循环冗余校验)的实际实现。(另请参见 ISO 3309 [ISO-3309] 或 ITU-T V.42 [ITU-T-V.42] 获取正式规范。)

示例代码使用 ISO C [ISO_9899] 编程语言。 31 中的提示可能有助于非 C 语言用户更轻松地阅读代码。

31 阅读 ISO C 代码的提示
运算符 描述
& 按位 AND 运算符。
^ 按位异或运算符。
>> 按位右移运算符。当应用于此处所示的无符号量时,右移会在左侧插入零。
! 逻辑 NOT 运算符。
++ n++”递增变量 n。在“for”循环中,它在变量被测试后应用。
0xNNN 0x 引入一个十六进制(以 16 为底)常量。后缀 L 表示长整型值(至少 32 位)。

/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];

/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;

/* Make the table for a fast CRC. */
void make_crc_table(void)
{
  unsigned long c;
  int n, k;

  for (n = 0; n < 256; n++) {
    c = (unsigned long) n;
    for (k = 0; k < 8; k++) {
      if (c & 1)
        c = 0xedb88320L ^ (c >> 1);
      else
        c = c >> 1;
    }
    crc_table[n] = c;
  }
  crc_table_computed = 1;
}
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
   should be initialized to all 1's, and the transmitted value
   is the 1's complement of the final running CRC (see the
   crc() routine below). */

unsigned long update_crc(unsigned long crc, unsigned char *buf,
                         int len)
{
  unsigned long c = crc;
  int n;

  if (!crc_table_computed)
    make_crc_table();
  for (n = 0; n < len; n++) {
    c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
  }
  return c;
}

/* Return the CRC of the bytes buf[0..len-1]. */
unsigned long crc(unsigned char *buf, int len)
{
  return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
}

E. 在线资源

本节是非规范性的。

引言

本附录提供了 PNG 软件开发人员的一些互联网资源位置。受互联网性质影响,该列表不完整且易于更改。

E.1 ICC 配置文件规范

ICC 配置文件规范可在以下网址获得:https://www.color.org/

E.2 PNG 网站

有一个 PNG 的万维网站点,网址为 http://www.libpng.org/pub/png/。该页面是获取关于 PNG 和 PNG 相关工具当前信息的中心位置。

关于 deflate 的额外文档和可移植 C 代码,以及优化的 CRC 算法实现,可从 zlib 网站 https://www.zlib.net/ 获取。

E.3 示例实现和测试图像

一个可移植 C 语言示例实现 libpng 可在 http://www.libpng.org/pub/png/libpng.html 获得。libpng 的示例查看器和编码器应用程序可在 http://www.libpng.org/pub/png/book/sources.html 获得,并在 PNG: The Definitive Guide [ROELOFS] 中有详细描述。测试图像也可以从 PNG 网站访问。

F. 变更

本节是非规范性的。

F.8 W3C 2003 年 11 月 10 日推荐标准(PNG 第二版)以来的更改

F.9 第一版与第二版之间的变更

有关 W3C 推荐标准 PNG 规范版本 1.0PNG 第二版 之间更改的列表,请参见 PNG 第二版更改列表

G. 参考资料

G.1 规范性参考资料

[BCP47]
语言标识标签. A. Phillips, Ed.; M. Davis, Ed. IETF. 2009年9月. 最佳当前实践. URL: https://www.rfc-editor.org/rfc/rfc5646
[CIPA-DC-008]
数码相机可交换图像文件格式:Exif 版本 2.32. 相机与影像产品协会 (CIPA). 2019-05-17. URL: https://www.cipa.jp/std/documents/download_e.html?DC-008-Translation-2019-E
[COLORIMETRY]
色度学,第四版。CIE 015:2018. CIE. 2018. URL: http://www.cie.co.at/publications/colorimetry-4th-edition
[Display-P3]
显示 P3 (Display P3). Apple, Inc. ICC. 2022-02. URL: https://www.color.org/chardata/rgb/DisplayP3.xalter
[ENCODING]
编码标准. Anne van Kesteren. WHATWG. 活标准. URL: https://encoding.spec.whatwg.org/
[ICC]
ICC.1:2022 (配置文件版本 4.4.0.0). 国际色彩联盟 (International Color Consortium). 2022年5月. URL: http://www.color.org/specification/ICC.1-2022-05.pdf
[ICC-2]
规范 ICC.2:2019 (配置文件版本 5.0.0 - iccMAX). 国际色彩联盟 (International Color Consortium). 2019. URL: https://www.color.org/specification/ICC.2-2019.pdf
[ISO_15076-1]
ISO 15076-1:2010 图像技术色彩管理 — 架构、配置文件格式与数据结构 — 第 1 部分:基于 ICC.1:2010. ISO. 2010-12. URL: https://www.iso.org/standard/54754.html
[ISO_8859-1]
ISO/IEC 8859-1:1998,信息技术 — 8 位单字节编码图形字符集 — 第 1 部分:拉丁字母 No. 1。. ISO. 1998.
[ISO_9899]
ISO/IEC 9899:2018 信息技术 — 编程语言 — C. ISO. 2018-6. URL: https://www.iso.org/standard/74528.html
[ISO-3309]
ISO/IEC 3309:1993,信息技术 — 电信与系统间信息交换 — 高级数据链路控制 (HDLC) 程序 — 帧结构。. ISO. 1993.
[ISO646]
信息技术 — 用于信息交换的 ISO 7 位编码字符集. 国际标准化组织 (ISO). 1991年12月. 已发布. URL: https://www.iso.org/standard/4777.html
[ITU-R-BT.2100]
ITU-R BT.2100,BT 系列:广播服务(电视)。用于制作与国际节目交换的高动态范围电视图像参数值. ITU. 2018-07. URL: https://www.itu.int/rec/R-REC-BT.2100
[ITU-R-BT.709]
ITU-R BT.709,BT 系列:广播服务(电视)。用于制作与国际节目交换的 HDTV 标准的参数值. ITU. 2015-06. URL: https://www.itu.int/rec/R-REC-BT.709
[ITU-T-H.273]
ITU-T H.273,H 系列:视听与多媒体系统 - 视听服务的基础设施 – 运动视频编码。用于视频信号类型识别的编码独立代码点. ITU. 2024-07-14. URL: https://www.itu.int/rec/T-REC-H.273
[ITU-T-Series-H-Supplement-19]
H 系列:视听与多媒体系统 - 视频信号类型代码点用法. ITU. 2021-04. URL: https://www.itu.int/ITU-T/recommendations/rec.aspx?rec=14652
[ITU-T-V.42]
ITU-T V.42,V 系列:电话网络上的数据通信。使用异步到同步转换的 DCE 纠错程序. ITU. 2002-03-29. URL: https://www.itu.int/rec/T-REC-V.42-200203-I/en
[JPEG]
JPEG 文件交换格式. Eric Hamilton. C-Cube Microsystems. 美国加利福尼亚州米尔皮塔斯. 1992年9月. URL: https://w3org.cn/Graphics/JPEG/jfif3.pdf
[Paeth]
图像文件压缩简易化,收录于《Graphics Gems II》,第 93-100 页. Paeth, A.W. Academic Press. 1991. URL: https://www.sciencedirect.com/science/article/pii/B9780080507545500293
[PNG-EXTENSIONS]
PNG 第三版规范扩展,版本 1.6.0. W3C. 2021. URL: https://w3c.github.io/png/extensions/Overview.html
[rfc1123]
互联网主机的要求 - 应用与支持. R. Braden, Ed. IETF. 1989年10月. 互联网标准. URL: https://www.rfc-editor.org/rfc/rfc1123
[rfc1950]
ZLIB 压缩数据格式规范版本 3.3. P. Deutsch; J-L. Gailly. IETF. 1996年5月. 信息性. URL: https://www.rfc-editor.org/rfc/rfc1950
[RFC1951]
DEFLATE 压缩数据格式规范版本 1.3. P. Deutsch. IETF. 1996年5月. 信息性. URL: https://www.rfc-editor.org/rfc/rfc1951
[RFC1952]
GZIP 文件格式规范版本 4.3. P. Deutsch. IETF. 1996年5月. 信息性. URL: https://www.rfc-editor.org/rfc/rfc1952
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997年3月. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[rfc3339]
互联网上的日期与时间:时间戳. G. Klyne; C. Newman. IETF. 2002年7月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc3339
[rfc3629]
UTF-8,一种 ISO 10646 的转换格式. F. Yergeau. IETF. 2003年11月. 互联网标准. URL: https://www.rfc-editor.org/rfc/rfc3629
[RFC8174]
RFC 2119 关键词中大小写的歧义. B. Leiba. IETF. 2017年5月. 最佳当前实践. URL: https://www.rfc-editor.org/rfc/rfc8174
[SMPTE-170M]
电视 — 复合模拟视频信号 — 工作室应用 NTSC. 电影与电视工程师协会 (SMPTE). 2004-11-30. URL: https://standards.globalspec.com/std/892300/SMPTE%20ST%20170M
[SMPTE-ST-2086]
支持高亮度与广色域图像的母版显示色彩体积元数据. 电影与电视工程师协会 (SMPTE). 2018年4月27日. URL: https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899
[SRGB]
多媒体系统与设备 - 色彩测量与管理 - 第 2-1 部分:色彩管理 - 默认 RGB 色彩空间 - sRGB. IEC. URL: https://webstore.iec.ch/publication/6169
[XMP]
可扩展元数据平台 (XMP) 规范 -- 第 1 部分. Adobe Systems Incorporated. ISO/IEC. 2019年4月. URL: https://www.iso.org/standard/75163.html
[Ziv-Lempel]
一种通用序列数据压缩算法,IEEE 信息论汇刊,第 IT-23 卷,第 3 期,第 337 - 343 页. J. Ziv; A. Lempel. IEEE. 1977-05. URL: https://ieeexplore.ieee.org/document/1055714

G.2 参考性参考资料

[COLOR-FAQ]
色彩常见问题解答. Poynton, C. 2009-10-19. URL: https://poynton.ca/ColorFAQ.html
[CTA-861.3-A]
HDR 静态元数据扩展 (CTA-861.3-A). 消费者技术协会 (CTA). 2015-01. URL: https://shop.cta.tech/products/cta-861-3
[EBU-R-103]
数字电视系统中的视频信号容差. EBU. 2020-05. URL: https://tech.ebu.ch/docs/r/r103.pdf
[GAMMA-FAQ]
Gamma 常见问题解答. Poynton, C. 1998-08-04. URL: https://poynton.ca/GammaFAQ.html
[GIF]
图形交换格式 (GIF). CompuServe Incorporated. 1990年7月31日. URL: https://w3org.cn/Graphics/GIF/spec-gif89a.txt
[HDR-Static-Meta]
关于 HDR 静态内容元数据的计算与用法. Smith, Michael D.; Zink, Michael. 电影与电视工程师协会 (SMPTE). 2021-08-05. URL: https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9508136
[HDR10]
HDR10 媒体配置文件. URL: https://en.wikipedia.org/wiki/HDR10
[Hill]
基于 CIELAB 色差公式的色彩空间量化比较分析. Hill, B.; Roger, Th.; Vorhagen, F.W. 1997-04. URL: https://dl.acm.org/doi/10.1145/248210.248212
[ITU-R-BT.2020]
用于制作与国际节目交换的超高清电视系统参数值. ITU. URL: https://www.itu.int/rec/R-REC-BT.2020
[ITU-R-BT.2390]
用于制作与国际节目交换的高动态范围电视. ITU. URL: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2390-11-2023-PDF-E.pdf
[Kasson]
计算机交换色彩空间分析. Kasson, J.; W. Plouffe. 1992. URL: https://dl.acm.org/doi/abs/10.1145/146443.146479
[PostScript]
PostScript 语言参考手册. Adobe Systems Incorporated. Addison-Wesley. 1990.
[ROELOFS]
PNG:权威指南. Roelofs, G. O'Reilly & Associates Inc. 1999-06-11. URL: http://www.libpng.org/pub/png/pngbook.html
[SMPTE-RP-177]
基础电视色彩方程的推导. 电影与电视工程师协会 (SMPTE). 1993年11月1日. URL: https://standards.globalspec.com/std/1284890/smpte-rp-177
[SMPTE-RP-2077]
全范围图像映射. 电影与电视工程师协会 (SMPTE). 2013-01-01. URL: https://doi.org/10.5594/SMPTE.RP2077.2013
[SMPTE-ST-2067-21]
可互操作母版格式 (IMF) — 应用 #2E. 电影与电视工程师协会 (SMPTE). 2023-02-20. URL: https://doi.org/10.5594/SMPTE.ST2067-21.2023
[TIFF-6.0]
TIFF 修订版 6.0. 1992年6月3日. URL: https://www.loc.gov/preservation/digital/formats/fdd/fdd000022.shtml