在Python中使用pngquant压缩png图片的教程
说到png图片压缩,可能很多人知道TinyPNG这个网站。但PS插件要钱(虽然有破解的),DeveloperAPI要连到他服务器去,不提网络传输速度,Key也是有每月限制的。
但是貌似tinyPNG是使用了来自于pngquant的技术,至少在http://pngquant.org/中是如此声称的:TinyPNGandKraken.io—on-lineinterfacesforpngquant。如果真是这样,我很想对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 usepngquanttoreducespngfilesize Ruoqian,Chen<piao.polar@gmail.com> ---------- 2015/4/3 1.deloption--quality=50-90,specialpicneedskipcanconfiginlodini lodiniformat: [PixelFormat] map_01.png=0 0meansskipinfile ---------- 2015/4/2 1.desDircanbethesametosrcDir,oranotherdir 2.lodiniconfigcanbenotexist ---------- 2015/3/31 create ''' importos importos.path importsys importConfigParser importstring PngquantExe="pngquant" thisFilePath=sys.path[0]; print"thispyfileindir:"+thisFilePath projectPath=thisFilePath+"/../CMWar_2dx/CMWar_2dx/"; srcResDir="Resources/"; dstResDir="Resources/"; lodIniPath=projectPath+srcResDir+"ini/pic.ini" keepOrgPaths=[]; ifos.path.exists(lodIniPath): config=ConfigParser.SafeConfigParser() config.read(lodIniPath) section="PixelFormat"; options=config.options(section) foroptioninoptions: value=string.atoi(config.get(section,option)) ifnotvalue: keepOrgPaths.append(option); printkeepOrgPaths srcResPath=projectPath+srcResDir; pngCount=0; transCount=0; #pngquant--force--skip-if-larger--ext.png--quality50-90--speed1 forparent,dirnames,filenamesinos.walk(srcResPath): print"-----processDir"+parent dstDir=parent.replace(srcResDir,dstResDir) ifnotos.path.exists(dstDir): os.makedirs(dstDir) forfilenameinfilenames: ifos.path.splitext(filename)[1]=='.png': pngCount+=1; srcFilePath=os.path.join(parent,filename); dstFilePath=os.path.join(dstDir,filename); tmpFilePath=dstFilePath+".tmp"; iffilenameinkeepOrgPaths: 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; #printcmd; os.system(cmd) ifos.path.exists(tmpFilePath): sizeNew=os.path.getsize(tmpFilePath); sizeOld=os.path.getsize(srcFilePath); ifsizeNew<sizeOld: open(dstFilePath,"wb").write(open(tmpFilePath,"rb").read()) transCount+=1; os.remove(tmpFilePath) ifnotos.path.exists(dstFilePath): open(dstFilePath,"wb").write(open(srcFilePath,"rb").read()) print"Done.TransPngs:%d/%d"%(transCount,pngCount)