使用 python 压缩 png 图片,高达 80% 压缩率,肉眼无差异(二):使用 pngquant 实现图片压缩

在网上有很多使用 python 的 pillow 库进行图片压缩的教程,使用简单,但是压缩效果存在明显的色彩不自然,这是因为 pillow 库采取的压缩算法没有优化的问题。

这个系列实现一款简单的压缩工具,使用 pngquant 有损压缩,压缩率高达 80%, 而且压缩后的图片没有明显差异。

系列文章:

1,使用 python 压缩 png 图片,高达 80% 压缩率,肉眼无差异(一):为什么不用 pillow库.md

2,使用 python 压缩 png 图片,高达 80% 压缩率,肉眼无差异(二):使用 pngquant 实现图片压缩

3,使用 python 压缩 png 图片,高达 80% 压缩率,肉眼无差异(三):使用 click 库实现命令行

4,使用 python 压缩 png 图片,高达 80% 压缩率,肉眼无差异(四):使用 requests 库上传

上一篇我尝试使用了 pillow 库对 png 图片进行了压缩,效果不好。这次我换用 pngquant 来压缩。 pngquant 是用于 PNG 图像有损压缩的命令行实用程序和库。压缩程序会显著减小文件大小(通常高达70%),并保持完全的alpha透明度。通过使用alpha通道将图像转换为更高效的8位PNG格式(通常比24/32位PNG文件小60-80%)。

pngquant 使用的算法主要是中值切割量化算法的改进版和 K-means 颜色校正。得到的图片颜色差异肉眼几乎无法察觉。

这是 pngquant 优化后的图片,几乎看不出区别: pngquant effect.jpg

这是 pillow 同样采用中值切割和 k-means 得到的优化效果, 云彩有明显颜色过渡不自然问题: quantize effect.jpg

pngquant 压缩库安装

pngquant 提供了源码、命令行和 GUI 等多种形式。它不是 python 写的,所以只能用 python 调用命令行或者源码函数。 GUI 的工具目前来说还比较难用,并没有命令行方便,而源码形式可以通过 ctype 使用 python语言去调用 c 源码。但是目前对这方面还不怎么了解,可以后面再去使用 so 动态库等方式。

先用命令行形式进行 PNG 压缩。

1,下载 windows安装包 或者 mac 和 linux 版本的安装包。

2,命令行输入 pngquant 就可以使用了;

3,为了使用方便,可以配置环境变量(后面如果和 picom 集成在了一起再去掉 )。

pngquant-fs8.pngpngquant-fs8.png

快速使用 pngquant

pngquant 图片名称.png

对于一些可选参数的说明:

1,--skip-if-larger pngquant 有时候压缩的文件会比源文件大。这个选项会判断,如果大就取消执行。强烈建议加上

2,--quality 0-100 图片质量。对于颜色没有特别要求的可以缩减到 10, 但是越小压缩率越低,通常不需要设置。

3,--force 强制执行,pngquant 会判断,如果有一个已经压缩的同名文件在当前文件夹,就不会执行。这个选项会覆盖原来的文件。

4,--output file 指定输入文件的名称。 可以指定为 jpg 格式,但是图片不会变得更小。

5,--speed 执行速度

使用 subprocess 调用 pngquant 命令行

对应的程序:

import subprocess
subprocess.run('pngquant elephant.png')

如果想获取程序运行时屏幕上显示的内容,可以使用 check_output 方法,在这里不需要。

接下来使用 subprocess 封装对应的压缩函数:

def pngquant_compress(fp, force=False, quality=None):
    """压缩函数.
    
    参数:
        fp: 文件名称
        force: 如果存在同名文件,是否覆盖
        quality: 压缩质量。 10-40, or 10
    """

    force_command = '-f' if force else ''
    
    quality_command = ''
    if quality and isinstance(quality, int):
        quality_command = f'--quality {quality}'
    if quality and isinstance(quality, str):
        quality_command = f'--quality {quality}'
    
    command = f'pngquant {fp} --skip-if-larger {force_command} {quality_command}'
    subprocess.run(command)


if __name__ == "__main__":
    pngquant_compress('elephant.png', force=True, quality=20)

总结

之前使用大多数教程推荐的 pillow 库,效果并不好。这次换用知名的 pngquant 以后,色彩已经用肉眼很难感知。 要实现对 png 图片的压缩率和图片效果的平衡,pngquant 真是个不错的工具。

posted @ 2020-04-26 20:57  和牛  阅读(3345)  评论(0编辑  收藏  举报