pngquant介绍
pngquant
是一个流行的命令行工具,用于无损压缩 PNG 图像文件。这种工具特别适用于需要优化图像文件大小的Web开发和设计,以提高网页加载速度和降低带宽使用
这个工具的名称前缀是png,可以知道这是针对png图像进行设置的工具
而"quant"在
pngquant
这个名称中是指"quantization"(量化)。在数字信号处理中,量化是指将连续的模拟信号转换为离散的数字信号的过程,这一过程涉及到减少信息或数据的表示方法。在图像处理中,颜色量化特指将图像中的颜色数减少到一个固定的数目,这有助于降低图像文件的大小。将这两个单词结合起来,就能够明白这个工具所针对的范围和作用了
pngquant作用
- 颜色量化:通过将图片中的颜色数量减少至256色以下来实现压缩,通常在视觉上保持相对高的质量。
- 文件大小减少:通常能显著减少图像文件的大小,便于网页快速加载和减少存储空间。
- 支持批处理:可以处理一个或多个文件,适合大量图像的压缩需要。
- 跨平台兼容:可在多个操作系统如 Windows、macOS 和 Linux 上使用。
命令参数
参数 | 描述 |
---|---|
input.png |
指定要压缩的PNG文件 |
-o output.png |
指定输出文件的名称 |
--quality=65-80 |
设定输出图像的质量范围(0-100) |
--force |
即使存在同名文件也覆盖输出文件 |
--speed=1 |
设置压缩速度(1=慢且好,11=快且差) |
pngquant下载安装
- pngquant提供下列两种下载方式,分别是GUI和Command-line方式
- GUI翻译过来就是可视化的意思,而Command-line则是命令行,Command就是我们平时使用win+r打开终端时输入cmd的全称写法
- 作为程序员来说,我们当然是更适合使用命令行方式,也更加高效
- 下载下来后是压缩包的形式,将其解压到我们放置环境变量配置的文件夹中,然后就可以去配置环境变量了
- 这里进行配置需要在系统变量中才行
- 在控制台进行检测版本,看是否能够有效反应
- pngquant --version
pngquant原理
pngquant 使用修改过的 Median Cut 量化算法以及其他技术来实现压缩 PNG 图像的目的。它的工作原理如下:
- 构建直方图: pngquant 首先会检查你的图片,记录里面每种颜色出现的次数。这就像是给每种颜色做一个人口普查,看看哪些颜色是常见的,哪些是少见的。
- 选择颜色盒子: 接着,它会把类似的颜色分到一组,称为"颜色盒子"。不同于其他简单的方法(比如只看颜色出现的次数),pngquant 试图确保这些盒子里的颜色彼此之间的差异尽可能小,这有助于保持图片的整体质量。
- 加权直方图: pngquant 对于图像中噪点较多或细节较少的区域,会在统计时降低它们的权重。这意味着在处理颜色时,会更注重图像中清晰和重要的部分。
- 优化颜色选择: 为了找到最合适的颜色分配,pngquant 会不断调整直方图,重复使用一种叫做 Median Cut 的方法,并尝试给不那么常见的颜色更多的机会被选择。这个过程有点像不断试错,看看哪种方法能更好地表示原始图像。
- 生成调色板: 最后,它使用一种叫做 Voronoi 迭代(类似于 K-means 算法)的技术来微调颜色,确保找到的颜色组合能够最好地代表原始图像。
- 颜色重新映射: 在将图像的原始颜色转换为新的调色板颜色时,pngquant 会特别注意不在细节较多的边缘区域使用颜色抖动(一种视觉上的技巧来模拟缺少的颜色),以避免不必要的视觉噪点。只有在多个相邻像素颜色相同并且不在边缘的地方,它才会使用这种方法来优化视觉效果。
Median Cut 量化算法
假设我们有一张 8x8 像素的彩色图像,每个像素由红色、绿色和蓝色通道组成,每个通道的值范围是 0 到 255。
初始步骤
- 开始时的集合:
- 首先,把图像中的每一个像素看作是一个小点,这些点有自己的颜色,由红、绿、蓝三种颜色组成,每种颜色的强度范围是0到255。
- 我们把这些颜色点全部放在一个大的集合里,称之为"颜色桶"。
划分过程
- 选择划分依据:
- 在这个大颜色桶中,我们找到变化最大的颜色通道来划分颜色,比如这里我们选择红色通道,因为它在这些颜色中变化最大。
- 按颜色划分:
- 接着,我们按红色通道的值对颜色进行排序,并找到中间的红色值作为划分点,假设这个值是120。
- 将红色值小于120的颜色放在一个新的子桶中,红色值大于或等于120的颜色放在另一个子桶中。
细分与优化
- 继续细分:
- 然后,我们再次在这些子桶中找到变化最大的颜色通道来进行细分。比如在一个子桶中,我们发现绿色通道的变化很大,就用绿色的中值来划分这个子桶。
- 重复这个过程,直到所有子桶中的颜色数目达到我们想要的程度,或者颜色的变化不再显著。
映射与量化
- 颜色映射:
- 最后,我们将图像中的每个像素颜色映射到这些子桶中颜色最接近的那一个。比如一个像素的颜色是 (110, 70, 180),我们就在这些子桶中找一个与它最相近的颜色,这里可能是 (100, 50, 200)。
通过这种方式,原始图像中的颜色从可能的数千种颜色减少到只有几种(这里是4种)。这样不仅可以大幅减小文件大小,还可以保持图像质量到一定程度。这个方法特别适合需要压缩图像而又不希望损失太多细节的情况。
pngquant使用案例
js
# 基本压缩,自动添加 `-fs8.png` 后缀
pngquant input.png
# 指定输出文件名
pngquant input.png -o output.png
# 设定质量范围,例如65-80,意味着尝试保持在此质量范围内压缩
pngquant --quality=65-80 input.png
# 处理当前目录下所有 PNG 文件
pngquant *.png
# 使用 --force 参数覆盖已存在的输出文件
pngquant --force input.png
# 设置压缩速度为最慢,通常能获得最好的压缩效果
pngquant --speed=1 input.png
Nodejs 中 调用pngquant
- 我们同样还是可以用
exec
命令调用 - 那在这里,我采用了wallpaper的一张超高清图片来进行测试使用,该高清图片足足有28.41MB
js
const { exec } = require("child_process")
exec('pngquant 28.41MB.png -o test.png')
js
const { exec } = require("child_process")
exec('pngquant 28.41MB.png --quality=82 --output test.png')//quality表示图片质量0-100值越大图片越大效果越好
js
const { exec } = require("child_process")
//--speed=1: 最慢的速度,产生最高质量的输出图像
//--speed=10: 最快的速度,但可能导致输出图像质量稍微降低
exec('pngquant 28.41MB.png --speed=1 --quality=82 --output test.png')
- 让我们来看经过上面代码测试,"瘦身"后的图片表现如何:
- 其中命令参数-o是--output的缩写形式
- 经过瘦身的图片,从28.41MB减少到了12.76MB,对于颜色表现如此复杂的图片,压缩效果都非常的不错。通过图片放大再放大,我们能够看到并没有因此出现失真的问题,高清的特性依旧保留
- 对于该项功能来说,是上传图片功能的必备技能,经过压缩的图片,会让服务器的压力大幅度的降低,成本也能够有所缩减
- 其他具体的细致化调整就不进行测试了,但由此可见,其中的调整自由度是很大的,能够给我们带来更好的便利