在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多线程编程(二):启动线程的两种方法
Apr 05 Python
Python之批量创建文件的实例讲解
May 10 Python
python判断字符串或者集合是否为空的实例
Jan 23 Python
python如何获取当前文件夹下所有文件名详解
Jan 25 Python
python之yield和Generator深入解析
Sep 18 Python
Python 实现顺序高斯消元法示例
Dec 09 Python
wxpython多线程防假死与线程间传递消息实例详解
Dec 13 Python
opencv python在视屏上截图功能的实现
Mar 05 Python
django中url映射规则和服务端响应顺序的实现
Apr 02 Python
python实现将列表中各个值快速赋值给多个变量
Apr 02 Python
使用Python实现批量ping操作方法
May 06 Python
Python数组变形的几种实现方法
May 30 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字符串截取的简单方法
2013/07/04 PHP
浅析ThinkPHP的模板输出功能
2014/07/01 PHP
Joomla数据库操作之JFactory::getDBO用法
2016/05/05 PHP
PHP下载文件的函数实例代码
2016/05/18 PHP
csdn 论坛技术区平均给分功能
2009/11/07 Javascript
JQuery Easyui Tree的oncheck事件实现代码
2010/05/28 Javascript
如何判断元素是否为HTMLElement元素
2013/12/06 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
2015/03/04 Javascript
JavaScript的React Web库的理念剖析及基础上手指南
2016/05/10 Javascript
Vue.js报错Failed to resolve filter问题的解决方法
2016/05/25 Javascript
详解AngularJS验证、过滤器、指令
2017/01/04 Javascript
laydate.js日期时间选择插件
2017/01/04 Javascript
详解Nodejs 通过 fs.createWriteStream 保存文件
2017/10/10 NodeJs
详解如何解决Vue和vue-template-compiler版本之间的问题
2018/09/17 Javascript
解决axios会发送两次请求,有个OPTIONS请求的问题
2018/10/25 Javascript
layui实现数据表格点击搜索功能
2020/03/26 Javascript
nuxt引入组件和公共样式的操作
2020/11/05 Javascript
如何在 Vue 中使用 JSX
2021/02/14 Vue.js
Django内容增加富文本功能的实例
2017/10/17 Python
轻松实现TensorFlow微信跳一跳的AI
2018/01/05 Python
PyQt5每天必学之组合框
2018/04/20 Python
详解python模块pychartdir安装及导入问题
2020/10/22 Python
关于python scrapy中添加cookie踩坑记录
2020/11/17 Python
html5拍照功能实现代码(htm5上传文件)
2013/12/11 HTML / CSS
Etam俄罗斯:法国女士内衣和家居服网上商店
2019/10/30 全球购物
大学优秀班集体申报材料
2014/05/23 职场文书
委托书怎么写
2014/07/31 职场文书
农林经济管理专业自荐信
2014/09/01 职场文书
表扬通报怎么写
2015/01/16 职场文书
语文复习计划
2015/01/19 职场文书
考勤制度通知
2015/04/25 职场文书
关爱留守儿童捐款倡议书
2015/04/27 职场文书
巴黎圣母院观后感
2015/06/10 职场文书
2019年亲子运动会口号
2019/10/11 职场文书
Python基础之hashlib模块详解
2021/05/06 Python
超级详细实用的pycharm常用快捷键
2021/05/12 Python