在Python中使用pngquant压缩png图片的教程


Posted in Python onApril 09, 2015

说到png图片压缩,可能很多人知道TinyPNG这个网站。但PS插件要钱(虽然有破解的),Developer API要连到他服务器去,不提网络传输速度,Key也是有每月限制的。
    
    但是貌似tinyPNG是使用了来自于 pngquant 的技术,至少在 http://pngquant.org/ 中是如此声称的:TinyPNG and Kraken.io — on-line interfaces for pngquant。如果真是这样,我很想对TinyPNG说呵呵。后者是开源的,连首页中提供的GUI工具也都是开源的。并且TinyPNG在首页的原理说明里面,一次都没提到pngquant

    我取了tinyPNG的首页上的示例图用pngquant命令行跑了一下,压缩率和显示效果差不多。

    pngquant首页上提供的工具中,Pngyu(http://nukesaq88.github.io/Pngyu/)是跨平台并且开源的,个人觉得已经相当好用了,直接把文件夹往里面拽就能递归处理,支持各种形式的生成方式(改名、覆盖、存储到其他目录等),压缩结束给出压缩比,并且还支持预览。

    但我还是会希望能够通过脚本来处理,一方面可定制性更强,一方面更方便整合到整个自动化的流程链中。于是我又拿出了python试图写点什么,谁知道……

    pngquant的命令行方式略坑……help中的参数说明和实际效果不一致,已经发现的问题有

    1. --force 参数无效,只要输出文件存在,就会报错,无视这个本用来指定覆写的参数
    2. --skip-if-larger 参数不正常,有时候生成文件明明比较小,也会被skip掉……

    不过好在python大法好,这些问题虽然命令行本身不能处理,但python可以在上层处理掉,下面就是目前实际使用的递归处理某文件夹png的脚本:

'''
pngquant.py
use pngquant to reduces png file size
Ruoqian, Chen<piao.polar@gmail.com> 

----------
2015/4/3
1. del option --quality=50-90, special pic need skip can config in lod ini

  lod ini format:

[PixelFormat]
map_01.png=0

  0 means skip in file

----------
2015/4/2
1. desDir can be the same to srcDir, or another dir
2. lod ini config can be not exist

----------
2015/3/31
create
'''

import os
import os.path
import sys
import ConfigParser
import string

PngquantExe="pngquant"

thisFilePath = sys.path[0];

print "this py file in dir : " + thisFilePath

projectPath = thisFilePath + "/../CMWar_2dx/CMWar_2dx/";
srcResDir = "Resources/";
dstResDir = "Resources/";

lodIniPath = projectPath + srcResDir + "ini/pic.ini"
keepOrgPaths = [];
if os.path.exists(lodIniPath):
  config = ConfigParser.SafeConfigParser()
  config.read(lodIniPath)
  section = "PixelFormat";
  options = config.options(section)
  for option in options:
    value = string.atoi(config.get(section, option))
    if not value:
      keepOrgPaths.append(option);

print keepOrgPaths

srcResPath = projectPath + srcResDir;

pngCount = 0;
transCount = 0;

#pngquant --force --skip-if-larger --ext .png --quality 50-90 --speed 1

for parent,dirnames,filenames in os.walk(srcResPath):
  print "----- process Dir " + parent
  dstDir = parent.replace(srcResDir, dstResDir)
  if not os.path.exists(dstDir):
    os.makedirs(dstDir)
  for filename in filenames:
    if os.path.splitext(filename)[1] == '.png':
      pngCount += 1;
      srcFilePath = os.path.join(parent, filename);
      dstFilePath = os.path.join(dstDir, filename);
      tmpFilePath = dstFilePath + ".tmp";

      if filename in keepOrgPaths:
        print "----- keep ----- " + filename;
      else:
#        print "----- process ----- " + filename;
#        cmd = "\"" + PngquantExe + "\"" + " --force --speed=1 --quality=50-90 -v " + srcFilePath + " -o " + tmpFilePath;
        cmd = "\"" + PngquantExe + "\"" + " --force --speed=1 " + srcFilePath + " -o " + tmpFilePath;
#        print cmd;
        os.system(cmd)
        if os.path.exists(tmpFilePath):
          sizeNew = os.path.getsize(tmpFilePath);
          sizeOld = os.path.getsize(srcFilePath);
          if sizeNew < sizeOld:
            open(dstFilePath, "wb").write(open(tmpFilePath, "rb").read())
            transCount += 1;
          os.remove(tmpFilePath)
      if not os.path.exists(dstFilePath):
        open(dstFilePath, "wb").write(open(srcFilePath, "rb").read())

print "Done. Trans Pngs: %d/%d" %(transCount, pngCount)

Python 相关文章推荐
Python简单删除列表中相同元素的方法示例
Jun 12 Python
Python实现购物程序思路及代码
Jul 24 Python
python 文件操作删除某行的实例
Sep 04 Python
opencv python 傅里叶变换的使用
Jul 21 Python
78行Python代码实现现微信撤回消息功能
Jul 26 Python
pandas 数据归一化以及行删除例程的方法
Nov 10 Python
python 计算两个列表的相关系数的实现
Aug 29 Python
python 有效的括号的实现代码示例
Nov 11 Python
使用Python的datetime库处理时间(RPA流程)
Nov 24 Python
selenium+python实现基本自动化测试的示例代码
Jan 27 Python
Python干货实战之八音符酱小游戏全过程详解
Oct 24 Python
python 多态 协议 鸭子类型详解
Nov 27 Python
python optparse模块使用实例
Apr 09 #Python
Python中处理时间的几种方法小结
Apr 09 #Python
Python CSV模块使用实例
Apr 09 #Python
Python常用随机数与随机字符串方法实例
Apr 09 #Python
在Python中使用CasperJS获取JS渲染生成的HTML内容的教程
Apr 09 #Python
举例讲解Python程序与系统shell交互的方式
Apr 09 #Python
使用Python中的cookielib模拟登录网站
Apr 09 #Python
You might like
解析php中如何直接执行SHELL
2013/06/28 PHP
用php和jQuery来实现“顶”和“踩”的投票功能
2016/10/13 PHP
PHP 使用二进制保存用户状态的实例
2018/01/29 PHP
JS操作XML中DTD介绍及使用方法分析
2019/07/04 PHP
imagettftext() 失效,不起作用
2021/03/09 PHP
YUI 读码日记之 YAHOO.util.Dom - Part.1
2008/03/22 Javascript
一个简单的JavaScript 日期计算算法
2009/09/11 Javascript
网页前端优化之滚动延时加载图片示例
2013/07/13 Javascript
open 动态修改img的onclick事件示例代码
2013/11/13 Javascript
jQuery元素选择器用法实例
2014/12/23 Javascript
javascript获取元素离文档各边距离的方法
2015/02/13 Javascript
深入理解jQuery之防止冒泡事件
2016/05/24 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
浅谈angularjs module返回对象的坑(推荐)
2016/10/21 Javascript
微信小程序 toast 详解及实例代码
2016/11/09 Javascript
jQuery页面弹出框实现文件上传
2017/02/09 Javascript
jQuery插件HighCharts绘制2D半圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
vue.js项目打包上线的图文教程
2017/11/16 Javascript
小程序实现左滑删除功能
2018/10/30 Javascript
PWA介绍及快速上手搭建一个PWA应用的方法
2019/01/27 Javascript
vue+echarts实现动态折线图的方法与注意
2020/09/01 Javascript
vue 获取url里参数的两种方法小结
2020/11/12 Javascript
Python 序列的方法总结
2016/10/18 Python
Python SVM(支持向量机)实现方法完整示例
2018/06/19 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
有关Python的22个编程技巧
2018/08/29 Python
Python3 执行Linux Bash命令的方法
2019/07/12 Python
Win10下安装并使用tensorflow-gpu1.8.0+python3.6全过程分析(显卡MX250+CUDA9.0+cudnn)
2020/02/17 Python
jupyter note 实现将数据保存为word
2020/04/14 Python
5 个强大的HTML5 API 函数推荐
2014/11/19 HTML / CSS
个人职业生涯规划书1500字
2013/12/31 职场文书
项目考察欢迎辞
2014/01/17 职场文书
应聘销售主管的求职信
2014/04/26 职场文书
环境科学专业求职信
2014/08/04 职场文书
小学优秀教师材料
2014/12/15 职场文书
详解Vue项目的打包方式(生成dist文件)
2022/01/18 Vue.js