Python批量压缩图片(TinyPNG)
什么是TinyPNG?
TinyPNG提供了PNG图片的“几乎无损”压缩服务。详细介绍TinyPNG
Mac客户端
Mac客户端下载地址
网上大多都是通过Python脚本实现,这里做一个简单的总结。
申请/查看Developer API
如果你是免费用户,那么每个developer key最多只能压500次
,可通过多注册几个邮箱的方式解决次数的限制。
这里邮箱不支持QQ邮箱
如果你之前有使用邮箱申请过API Key
可以登录来查看邮箱关联的API Key
TinyPNG平台没有密码机制自能发送邮件来关联登录
环境准备
以下为笔者测试通过的Mac环境
1、Python版本2.7.10
(Mac默认有安装Python)
查看Python 版本python -V
,如果没有安装Mac电脑建议使用brew包管理工具安装brew install python
2、pip版本为10.0.1
pip安装参考文档
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.pypython get-pip.py
3、安装Python的tinify模板库
pip install --upgrade tinify
Python脚本
新建tinypng.py
文件复制以下脚本并保存
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import sys
import csv
import os.path
import tinify
from PIL import Image
from optparse import OptionParser
#请替换为自己申请的Key
tinify.key = ""
png_path = []
png_path_compressed = []
def get_png_path(inputPath):
for p in os.listdir(inputPath):
temp_path = os.path.join(inputPath,p)
if os.path.isdir(temp_path):
get_png_path(temp_path)
else:
if os.path.splitext(p)[1] == '.png' or os.path.splitext(p)[1] == 'jpg' or os.path.splitext(p)[1] == 'jpeg':
print "PNG File:",os.path.join(inputPath,p)
png_path.append(os.path.join(inputPath,p))
def compress_core(inputFile, outputFile, img_width):
source = tinify.from_file(inputFile)
if img_width is not None:
resized = source.resize(method = "scale", width = img_width)
resized.to_file(outputFile)
else:
source.to_file(outputFile)
def compress_path(path, width):
print "compress_path-------------------------------------"
if not os.path.isdir(path):
print "这不是一个文件夹,请输入文件夹的正确路径!"
return
else:
fromFilePath = path # 源路径
toFilePath = path+"/tiny" # 输出路径
print "fromFilePath=%s" %fromFilePath
print "toFilePath=%s" %toFilePath
for root, dirs, files in os.walk(fromFilePath):
print "root = %s" %root
print "dirs = %s" %dirs
print "files= %s" %files
for name in files:
fileName, fileSuffix = os.path.splitext(name)
if fileSuffix == '.png' or fileSuffix == '.jpg' or fileSuffix == '.jpeg':
toFullPath = toFilePath + root[len(fromFilePath):]
toFullName = toFullPath + '/' + name
if os.path.isdir(toFullPath):
pass
else:
os.mkdir(toFullPath)
compress_core(root + '/' + name, toFullName, width)
break # 仅遍历当前目录
# 仅压缩指定文件
def compress_file(inputFile, width):
print "compress_file-------------------------------------"
if not os.path.isfile(inputFile):
print "这不是一个文件,请输入文件的正确路径!"
return
print "file = %s" %inputFile
dirname = os.path.dirname(inputFile)
basename = os.path.basename(inputFile)
fileName, fileSuffix = os.path.splitext(basename)
if fileSuffix == '.png' or fileSuffix == '.jpg' or fileSuffix == '.jpeg':
mkdir(dirname+"/tiny");
png_path_compressed.append(dirname+"/tiny/"+basename)
compress_core(inputFile, dirname+"/tiny/"+basename, width)
else:
print "不支持该文件类型!"
def mkdir(path):
folder = os.path.exists(path)
if not folder: #判断是否存在文件夹如果不存在则创建为文件夹
os.makedirs(path) #makedirs 创建文件时如果路径不存在会创建这个路径
print "--- new folder... ---"
print "--- OK ---"
else:
print "--- There is this folder! ---"
def run(file, dir=None, width=None):
if file is not None:
print "仅压缩一个文件!"
compress_file(file, width) # 仅压缩一个文件
pass
elif dir is not None:
print "压缩指定目录下的文件!"
compress_path(dir, width) # 压缩指定目录下的文件
pass
else:
print "压缩当前目录下的文件!"
compress_path(os.getcwd(), width) # 压缩当前目录下的文件
def get_compressed_result():
for png in png_path:
run(os.path.abspath(png))
rows = []
row = ()
for i in range(len(png_path)):
img = Image.open(png_path[i])
imgSize = img.size
before_compressed = os.stat(png_path[i]).st_size
after_compressed = os.stat(png_path_compressed[i]).st_size
print png_path[i],before_compressed,after_compressed,(before_compressed - after_compressed) *1.0/ before_compressed
if imgSize[0] * imgSize[1] > 1024* 1024:
too_large_scale = "True"
else:
too_large_scale = "False"
row = (png_path[i],before_compressed,after_compressed,(before_compressed - after_compressed) *1.0/ before_compressed,imgSize[0],imgSize[1],too_large_scale)
rows.append(row)
header = [u'Path',u'before_compressed',u'after_compressed',u'compression_rate',u'width',u'height',u'too_large_scale']
with open('compressed.csv','wb') as f:
f_csv = csv.writer(f)
f_csv.writerow(header)
f_csv.writerows(rows)
if __name__ == "__main__":
usage = '''python tinypng.py [options]
-example: python tinypng.py -d xxx
'''
parser = OptionParser(usage)
parser.add_option('-d', dest='_path', help=u'(必选)指定游戏脚本路径')
(options, args) = parser.parse_args()
if not options._path:
print '\n -d 参数必须设置!'
print usage
sys.exit(1)
get_png_path(options._path)
get_compressed_result()
执行批量压缩
进入tinypng.py
文件所在目录执行以下命令
python tinypng.py -d ya
-d 后面为要压缩图片的文件夹路径
完整示例
要压缩的图片在/Users/Javen/Documents/dev/img/ya
中,tinypng.py
文件在/Users/Javen/Documents/dev/img/
中,如下图所示
执行压缩命令
压缩后效果图