在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 相关文章推荐
Django1.7+python 2.78+pycharm配置mysql数据库教程
Nov 18 Python
玩转python爬虫之cookie使用方法
Feb 17 Python
Python使用logging结合decorator模式实现优化日志输出的方法
Apr 16 Python
Python基于numpy灵活定义神经网络结构的方法
Aug 19 Python
python实现飞机大战微信小游戏
Mar 21 Python
python实现Zabbix-API监控
Sep 17 Python
Python jieba库用法及实例解析
Nov 04 Python
python和php学习哪个更有发展
Jun 17 Python
Python延迟绑定问题原理及解决方案
Aug 04 Python
如何使用 Python 读取文件和照片的创建日期
Sep 05 Python
python基于exchange函数发送邮件过程详解
Nov 06 Python
详解Pycharm第三方库的安装及使用方法
Dec 29 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
PHP4实际应用经验篇(3)
2006/10/09 PHP
谈谈PHP的输入输出流
2007/02/14 PHP
php email邮箱正则
2008/10/08 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
JS编程小常识很有用
2012/11/26 Javascript
js Math 对象的方法
2013/09/01 Javascript
jQuery实现的网页左侧在线客服效果代码
2015/10/23 Javascript
牛叉的Jquery——Jquery与DOM对象的互相转换及DOM的三种操作
2015/10/29 Javascript
JS实现获取剪贴板内容的方法
2016/06/21 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
浅谈jQuery hover(over, out)事件函数
2016/12/03 Javascript
jQuery基于Ajax方式提交表单功能示例
2017/02/10 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
vue.js 获取当前自定义属性值
2017/06/01 Javascript
JS实现的随机排序功能算法示例
2017/06/09 Javascript
jQuery ajax读取本地json文件的实例
2017/10/31 jQuery
vue.js实现点击后动态添加class及删除同级class的实现代码
2018/04/04 Javascript
微信小程序实现简单表格
2019/02/14 Javascript
JS事件绑定的常用方式实例总结
2019/03/02 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
Vue混入mixins滚动触底的方法
2019/11/22 Javascript
详解Python map函数及Python map()函数的用法
2017/11/16 Python
python实现socket+threading处理多连接的方法
2019/07/23 Python
django foreignkey(外键)的实现
2019/07/29 Python
python 实现控制鼠标键盘
2020/11/27 Python
Amaze UI 文件选择域的示例代码
2020/08/26 HTML / CSS
Web Service面试题:如何搭建Axis2的开发环境
2012/06/20 面试题
自我鉴定注意事项
2014/01/19 职场文书
超市重阳节活动方案
2014/02/10 职场文书
公务员群众路线专题民主生活会发言材料
2014/09/17 职场文书
《改造我们的学习》心得体会
2014/11/07 职场文书
幼儿园小班工作总结2015
2015/04/25 职场文书
2016年119消防宣传日活动总结
2016/04/05 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
Java界面编程实现界面跳转
2022/06/16 Java/Android
JS前端宏任务微任务及Event Loop使用详解
2022/07/23 Javascript