在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实现统计文本文件字数的方法
May 05 Python
对numpy Array [: ,] 的取值方法详解
Jul 02 Python
解决tensorflow1.x版本加载saver.restore目录报错的问题
Jul 26 Python
用Python编写一个高效的端口扫描器的方法
Dec 20 Python
python生成器与迭代器详解
Jan 01 Python
Python实现个人微信号自动监控告警的示例
Jul 03 Python
将Python文件打包成.EXE可执行文件的方法
Aug 11 Python
Python 时间戳之获取整点凌晨时间戳的操作方法
Jan 28 Python
python实现俄罗斯方块游戏(改进版)
Mar 13 Python
PyQt5 界面显示无响应的实现
Mar 26 Python
Python GUI编程学习笔记之tkinter控件的介绍及基本使用方法详解
Mar 30 Python
python中@contextmanager实例用法
Feb 07 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和MySql中计算时间差的方法
2011/04/22 PHP
php数组函数序列之array_key_exists() - 查找数组键名是否存在
2011/10/29 PHP
编写Smarty插件在模板中直接加载数据的详细介绍
2013/06/26 PHP
php获取新浪微博数据API实例
2013/11/12 PHP
php获取错误信息的方法
2015/07/17 PHP
PHP类的声明与实例化及构造方法与析构方法详解
2016/01/26 PHP
一次失败的jQuery优化尝试小结
2011/02/06 Javascript
JavaScript词法作用域与调用对象深入理解
2012/11/29 Javascript
JQuery-tableDnD 拖拽的基本使用介绍
2013/07/04 Javascript
jQuery中removeData()方法用法实例
2014/12/27 Javascript
Jquery与Bootstrap实现后台管理页面增删改查功能示例
2017/01/22 Javascript
knockoutjs模板实现树形结构列表
2017/07/31 Javascript
node.js 利用流实现读写同步,边读边写的方法
2017/09/11 Javascript
详解RequireJs官方使用教程
2017/10/31 Javascript
jQuery实现浏览器之间跳转并传递参数功能【支持中文字符】
2018/03/28 jQuery
React Native 混合开发多入口加载方式详解
2019/09/23 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
vue项目中使用eslint+prettier规范与检查代码的方法
2020/01/16 Javascript
Vue Element校验validate的实例
2020/09/21 Javascript
区分vue-router的hash和history模式
2020/10/03 Javascript
Pycharm技巧之代码跳转该如何回退
2017/07/16 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
Window 64位下python3.6.2环境搭建图文教程
2018/09/19 Python
python中退出多层循环的方法
2018/11/27 Python
python文字转语音的实例代码分析
2019/11/12 Python
Python解压 rar、zip、tar文件的方法
2019/11/19 Python
python中upper是做什么用的
2020/07/20 Python
pymysql模块使用简介与示例
2020/11/17 Python
Theory美国官网:后现代都市风时装品牌
2018/05/09 全球购物
硕士研究生个人求职信
2013/12/04 职场文书
领导调研接待方案
2014/02/27 职场文书
法院授权委托书范文
2014/08/02 职场文书
爱牙日活动总结
2014/08/29 职场文书
个人自荐书怎么写
2015/03/26 职场文书
农业项目合作意向书
2015/05/08 职场文书
儿子满月酒致辞
2015/07/29 职场文书