图形学 | 格物致知!PNG 除了无损压缩你还知道什么?

简介: 图形学 | 格物致知!PNG 除了无损压缩你还知道什么?

前言


  • PNG(Protable Network Graphics,便携式网络图形) 是一种非常常见的图片格式,深入理解 PNG 文件原理,有利于加强对图片编解码过程的理解,便于开展优化工作。
  • 在这篇文章里,我将带你探究 PNG 图片的 数据结构 & 编码原理 & 优化方法等。如果能帮上忙,请务必点赞加关注,这真的对我非常重要。


系列文章




目录

image.png

1. 概述


1.1 定义


PNG(Portable Network Graphics,便携式网络图形)是一种 无损压缩的位图图形格式。它本身的设计目的是替代 GIF 格式,所以它与 GIF 有一些相似之处。


1.1 特点


  • 无损压缩(Lossless Compression):采用了 LZ77 派生算法 + Huffman 编码,压缩率更高,体积更小且不损失数据;
  • 支持透明:支持 8 位透明通道,而 GIF 只支持 1 比特透明通道,JPEG 不支持透明通道;
  • 图像的复杂程度越低,使用 PNG  格式的压缩率更高(原因见 第 3 节 编码原理);
  • 支持五种像素 / 颜色类型


  • 索引色(Indexed-colour,8 位)
  • 灰度(Greyscale,8 位)
  • 真彩色(Truecolour,24 位)
  • 灰度透明(Greyscale with alpha,16 位)
  • 真彩色透明(Truecolour with alpha,32 位)

image.png

引用自 www.w3.org/TR/2003/REC… —— w3.org


提示: 网上所述三种 PNG 类型为:PNG 8、PNG 24、PNG 32,经查阅百科、PNG 官网和《PNG 文件协议》未能找到支撑依据,本文不作阐述。


2. PNG 数据结构


这一节我们来讨论 PNG 图片的数据结构,一个 PNG 格式文件(或数据流)由一个 8 字节的签名和若干个数据块(chunk)组成。


2.1 PNG 签名


PNG 文件头部的 8 字节为文件签名(或称魔数),这个值将被用来识别文件是否为 PNG 文件,数据固定为8950 4E47 0D0A 1A0A。以下是我任意打开的一个 PNG 文件:

image.png


提示: 使用 010 Editor 可以查看文件二进制数据。首次打开 PNG 文件时,它会提示安装 PNG.bt,安装后将帮助解析你读懂每块数据的含义。


2.2 数据块


  • 数据块类型

PNG 定义了两种数据块:关键数据块(critical chunks)& 辅助数据块(ancillary chunks)。


其中,关键数据块是从 PNG 数据流中成功解码图像所必需的,而辅助数据块是可选的,我们将重点了解关键数据块。关键数据块分为四种:文件头数据块、调色板数据块、图像数据块和图像结束数据块。


  • 数据块的内部结构


PNG 的每一块数据块都由四个部分组成:


名称 字节数 描述
长度(length) 4 指定数据块中数据域的长度
数据块类型码(Chunk Type Code) 4 由(A-Z、a-z)组成
数据 length 数据块数据
循环冗余检测(CRC) 4 用于检错
  • 文件头数据块 IDHR(header chunk)


文件头数据块是 PNG 文件中的第一个数据块,包含了 PNG 文件的基本信息,由 13 个字节组成,数据结构如下:


字段 字节数 描述
图片宽度(Width) 4 以像素为单位
图片高度(Height) 4 以像素为单位
图像深度(Bit depth) 1 /
颜色类型(ColorType) 1 5 种颜色类型:
索引色
灰度
灰度透明
真彩色(24 位直接色)
真彩色透明(32 位直接色)
压缩方法(Compression method) 1 LZ77 派生算法
滤波方法(Filter method) 1 /
隔行扫描方法(Interface method) 1 0:非隔行扫描
1: Adam7(7遍隔行扫描方法)
  • 调色板数据块 PLTE(palette chunk)


调色板数据块包含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块 IDAT 之前。真彩色的 PNG 数据流也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。


  • 图像数据块 IDAT(image data chunk)

图像数据块是图像实际存储的数据,可包含多个连续顺序的图像数据块。

  • 图像结束数据块 IEND(image trailer chunk)

图像结束数据块标记 PNG 文件或者数据流已经结束,必须要放在尾部。


3. PNG 编码原理


通过查阅《Protable Network Graphic (PNG) Specification (Second Edition)》,可以了解到 PNG 文件的编码过程主要分为五个阶段:


  • 1、通过提取(pass extraction)
  • 2、扫描线序列化(scanline serialization)
  • 3、过滤(filtering)
  • 4、压缩(compression)
  • 5、分块(chunking)


前两个步骤我看不懂,我直接讲后三个步骤。

image.png

3.3 滤波(filtering)


这个步骤的主要思想是 增量编码,即:一个值可以表示为与前值的差值。


例如:[2,3,4,5,6,7,8][2,3,4,5,6,7,8][2,3,4,5,6,7,8]可以编码为[2,3−2=1,4−3=1,5−4=1,6−5=1,7−6=1,8−7=1][2,3-2=1,4-3=1,5-4=1,6-5=1,7-6=1,8-7=1][2,3−2=1,4−3=1,5−4=1,6−5=1,7−6=1,8−7=1] =>[2,1,1,1,1,1,1][2,1,1,1,1,1,1][2,1,1,1,1,1,1]


可以发现,增量编码后的数据变成了大量重复、低值的数据,这样的数据是有利于压缩的,原因我在 第 3.4 节 说。


回到 PNG 的滤波步骤,这个步骤主要是选择合适的差分过滤器,分别处理每一行中的每个像素,使得差分编码的数值尽可能重复、尽可能小,要点如下:


  • 1、滤波器有以下五种

image.png

引用自 zh.wikipedia.org/wiki/PNG —— 维基百科

在后面的 分块(chunking) 步骤中,会把编码过程中使用的滤波方法被记录 IHDR 中的Filter method字段里。


  • 2、为了最优效果,每一行可使用不同滤波器

image.png

引用自 medium.com/@duhroach/h… —— Colt McAnlis 著


  • 3、滤波却是按通道而不是按像素进行的

滤波是按通道而不是按像素进行的,也就是说滤波是先扫描一行中像素的红色通道,然后再扫描一行中像素的蓝色通道,以此类推。


  • 4、一行中所有通道使用相同的滤波器


3.4 压缩(compression)


PNG 的压缩过程结合了 LZ77 编码和 Huffman 编码,要点如下:


  • 1、压缩过程是无损压缩
  • 2、颜色越单一,颜色差异越小,压缩率越大


LZ77 编码

一种基于字典的、“滑动窗”的无损压缩算法。

Huffman 编码(霍夫曼编码)

一种用于无损压缩的变长编码,主要思想为:评估码元的出现几率选择不同长度的编码,几率较高的码元使用较短的编码,而几率较低的码元使用较长的编码,这将使得编码的平均长度降低。


3.5 分块(chunking)


分块可方便地将压缩数据流分解为可管理的块,关于数据块的结构我们在 第 2 节中讨论过。


4. 缩小 PNG 文件大小


4.1 减少颜色数量 & 差异


在 第 3 节 编码原理 的讨论,我们提到了 增量编码 的概念,通过减少颜色的数量 & 差异,滤波步骤之后数据的差异更小,有利于在压缩步骤中缩小文件。


不过,减少颜色的数量 & 差异等同于给图片进行了有损编码,应当确保在高效压缩和图片质量之间保持适当的平衡。


4.2 采用索引色格式


如果图片的单色数量不超过 256 个,则可以采用Indexed-colour(索引色)格式。原始图像的每个像素由调色板中的一个索引表示。此时,每个像素的字节数由 3 字节(无透明通道)和 4 字节(有透明通道)减少到 1 字节,大大缩小文件。

image.png


引用自 developer.android.com/topic/perfo… —— Android Developers


4.3 采用矢量量化(vector quantization)


如果图片的单色数量超过 256 个,就需要 采用矢量量化较少颜色数量,再生成索引色格式。矢量量化就是将颜色相似的一块区域合并为同一种颜色的舍入的过程,主要分为以下步骤:


  • 1、根据相近区域相似度进行分组;
  • 2、将该组中所有颜色替换为单个中心点的颜色;
  • 3、生成索引色格式。

image.png

引用自 developer.android.com/topic/perfo… —— Android Developers


5. PNG 的有损压缩方案


在 第 3 节 编码原理 中我们提到了 PNG 压缩是无损压缩,为了进一步提高压缩率,可以采用有损压缩算法,以下是现有的 PNG 有损压缩方案。


在官网介绍中,其实可以清楚地了解到它们的原理,主要就是采用了 第 4.3 节 讨论的方案:采用矢量量化较少颜色数量,再生成索引色格式。


5.1 TinyPNG


官方地址:tinypng.com


How does it work?

...... This technique is called “quantization”. By reducing the number of colors, 24-bit PNG files can be converted to much smaller 8-bit indexed color images. All unnecessary metadata is stripped too. The result better PNG files with 100% support for transparency. Have your cake and eat it too!


局限:只提供了 HTTP 请求的方式,并且有次数限制。


5.2 pngquant


官方地址:pngquant.org


Features

High-quality palette generation using a combination of vector quantization algorithms. ......


5.3 zopflipng


5.4 pngcursh


Editting...

目录
相关文章
PDF-XChange 注册码
PDF-XChange Viewer Pro 注册码: User Name     : Team EAT Organization   : EATiSO Email address : teameat@no_email.com Key code         : PXP50-6TUFA-Z4R48-3H1KG-IXM7Z-6TLLP PDF-XChange简介:百度百科
9692 0
|
缓存 并行计算 前端开发
《十万线段绘乾坤:Canvas离屏渲染深度剖析》
本文聚焦Canvas绘制10万条动态线段时的帧率暴跌问题,深入解析离屏渲染的解决方案。常规渲染因高频实时绘制易超屏幕刷新时间窗口,导致卡顿。离屏渲染通过独立缓冲区预先绘制完整帧,再一次性输出到屏幕,减少实时绘制次数,利用GPU并行计算提升效率。文中还介绍了缓冲区规划、缓存机制、双缓冲协调等应用策略,以及应对资源消耗、上下文切换等挑战的方法,为前端开发者处理复杂图形绘制提供了关键技术指引。
481 0
|
存储 人工智能 数据可视化
2025年技术团队必看:10款提升研发效率的知识管理工具深度评测
在数字化时代,知识管理已成为提升个人与企业竞争力的关键。2025年,随着AI、大数据和云计算的发展,知识管理工具正向智能化、协作化方向演进。本文精选10款必备工具,涵盖Notion、Obsidian、语雀、飞书文档等,助你构建高效知识体系,把握未来趋势。
1652 0
|
机器学习/深度学习 存储 人工智能
基于AI的实时监控系统:技术架构与挑战分析
AI视频监控系统利用计算机视觉和深度学习技术,实现实时分析与智能识别,显著提升高风险场所如监狱的安全性。系统架构包括数据采集、预处理、行为分析、实时决策及数据存储层,涵盖高分辨率视频传输、图像增强、目标检测、异常行为识别等关键技术。面对算法优化、实时性和系统集成等挑战,通过数据增强、边缘计算和模块化设计等方法解决。未来,AI技术的进步将进一步提高监控系统的智能化水平和应对复杂安全挑战的能力。
3863 4
|
机器学习/深度学习 存储 人工智能
EfficientTAM:Meta AI推出的视频对象分割和跟踪模型
EfficientTAM是Meta AI推出的轻量级视频对象分割和跟踪模型,旨在解决SAM 2模型在移动设备上部署时的高计算复杂度问题。该模型采用非层次化Vision Transformer(ViT)作为图像编码器,并引入高效记忆模块,以降低计算复杂度,同时保持高质量的分割结果。EfficientTAM在多个视频分割基准测试中表现出与SAM 2相当的性能,具有更快的处理速度和更少的参数,特别适用于移动设备上的视频对象分割应用。
766 9
EfficientTAM:Meta AI推出的视频对象分割和跟踪模型
|
图形学
unity判断鼠标在不在UI上
在 Unity 中,判断鼠标是否在 UI 上主要依赖事件系统和射线检测机制。Unity 的事件系统负责处理输入事件,GraphicRaycaster 组件用于检测射线与 UI 元素的相交情况。通过 `EventSystem.current.IsPointerOverGameObject()` 方法可轻松判断鼠标是否在 UI 上。对于移动端,使用 `EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)` 来判断触摸是否在 UI 上。代码实现简单且高效。
|
C语言
ASCII编码的52个大小写字母
ASCII编码的52个大小写字母
30403 1
|
机器学习/深度学习 算法 数据库
R-CNN论文详解(入门目标检测必读)
R-CNN论文详解(入门目标检测必读)
R-CNN论文详解(入门目标检测必读)
|
编译器 C语言 计算机视觉
【ARM汇编速成】零基础入门汇编语言之指令集(二)
【ARM汇编速成】零基础入门汇编语言之指令集(二)