最近闲着没事,大佬便分配个压缩图片的任务给我。于是,我就上网找寻相对需求而言最优的解决方案。
初步实践后,得出结论:pngquant与ImageMagick各方面都符合需求。
![](https://img-blog.csdnimg.cn/20190731203037457.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hybHIxMjMw,size_16,color_FFFFFF,t_70)
ImageMagick下载地址 :http://www.imagemagick.org/script/download.php/
pngquant下载地址: http://pngquant.org/
我的是windows系统,所以选择下载windows版的。
![](https://img-blog.csdnimg.cn/20190731205443192.jpg)
pngquant_window.zip解压后用到的是pngquant.exe。你可以把它添加进系统变量,也可直接放在.py文件的目录下调用。
ImageMagick则运行exe安装。一路next之后,安装完成。如果你是使用PyCharm编辑,且安装之前打开的话,需重启PyCharm才能调用'magick'命令。
准备工作都做好了,上代码。
#!/usr/bin/python
# coding=utf-8
import os
import time
import shutil
import math
# PYTHON 2.7
srcPath = r"./tsimg"
savePath = r"./pngquantImg1"
# 运行命令行
def runSystem(ossys):
result = os.system(ossys)
if result == 0:
print(str(ossys) + ' success')
return True
else:
print(str(ossys) + ' fail')
return False
# 删除空文件夹
def delete_null_dir(dirr):
if os.path.isdir(dirr):
for p in os.listdir(dirr):
d = os.path.join(dirr, p)
if (os.path.isdir(d) == True):
delete_null_dir(d)
if not os.listdir(dirr):
os.rmdir(dirr)
# pngqyant 参数:
# --ext new.png 新名字(不传就默认后缀加'-or8.png' 或 '-fs8.png') 好像不行 用 -o new.png 可以
# --quality min-max 指示pngquant使用满足或超过最大质量所需的最少颜色量
# --speed 速度/质量权衡从1(蛮力)到10(最快)。默认值为3。速度10的质量降低5%,但比默认速度快8倍。
# --iebug E6的解决方案,它只显示完全不透明的像素。pngquant将使几乎不透明的像素完全不透明,并避免创建新的透明颜色
# --version 将版本信息打印到stdout
# - 从stdin读取图像并将结果发送到stdout
# -- 停止处理参数。这允许使用以-开头的文件名。如果在脚本中使用pngquant,建议将其放在文件名之前:pngquant $OPTIONS -- "$FILE"
# 网上说的
# --force 参数无效,只要输出文件存在,就会报错,无视这个本用来指定覆写的参数
# --skip-if-larger 参数不正常,有时候生成文件明明比较小,也会被skip掉……
def usePngQuantAndImageMagickAPI(max_size):
if os.path.exists(savePath):
shutil.rmtree(savePath, True)
print(savePath)
os.mkdir(savePath)
for n, f, file in os.walk(srcPath):
if len(file) != 0:
for i in file:
filetotledir = os.path.join(n, i)
temp_savePath = n.replace(srcPath, savePath)
if not os.path.exists(temp_savePath):
os.makedirs(temp_savePath)
filetotledir1 = os.path.join(temp_savePath, i)
CompressImage(filetotledir, max_size, filetotledir1) # 75
else:
continue
delete_null_dir(savePath)
def CompressImage(image_name, max_size, replace_name=''):
image_stat = os.stat(image_name)
image_size = image_stat.st_size / 1024.0 # 计算KB
print 'st_size:{0} image_size:{1}'.format(image_stat.st_size, image_size)
global g_total
global g_compress_size
global png_array
global jpg_array
global g_pic_num
global g_compress_pic_num
if image_size > max_size and not '.meta' in image_name:
compress_factor = max_size / image_size * 500 # 100
base_name = os.path.basename(image_name)
print("compressing :{0} compress_factor:{1} basename:{2}".format(image_name, compress_factor, base_name))
for ext_name in png_array:
if ext_name in image_name:
compress_factor = math.trunc(round(compress_factor))
if compress_factor > 90:
compress_factor = 85
# if compress_factor < 75:
# compress_factor = 75
iscompress = runSystem('pngquant.exe --force --verbose --speed=1 --quality={2}-100 {0} -o {1}'
.format(image_name, replace_name, compress_factor))
if iscompress:
g_compress_size = g_compress_size + math.ceil(os.stat(replace_name).st_size / 1024.0)
g_compress_pic_num = g_compress_pic_num + 1
g_total = g_total + math.ceil(image_size)
g_pic_num = g_pic_num + 1
break
for ext_name in jpg_array:
if ext_name in image_name:
iscompress = runSystem('magick convert {0} -quality {1} {2}'
.format(image_name, compress_factor, replace_name))
if iscompress:
g_compress_size = g_compress_size + math.ceil(os.stat(replace_name).st_size / 1024.0)
g_compress_pic_num = g_compress_pic_num + 1
g_total = g_total + math.ceil(image_size)
g_pic_num = g_pic_num + 1
break
elif not '.meta' in image_name: # 不复制原图,只记大小
for ext_name in png_array:
if ext_name in image_name:
# shutil.copy(image_name, replace_name)
g_total = g_total + math.ceil(image_size)
g_pic_num = g_pic_num + 1
break
for ext_name in jpg_array:
if ext_name in image_name:
# shutil.copy(image_name, replace_name)
g_total = g_total + math.ceil(image_size)
g_pic_num = g_pic_num + 1
break
if __name__ == "__main__":
# 给个默认值
time1 = time.time()
# 图片总大小
global g_total
g_total = 0
# 图片压缩大小
global g_compress_size
g_compress_size = 0
# png
global png_array
png_array = ['.png', '.PNG']
# jpg
global jpg_array
jpg_array = ['.JPG', '.jpg', '.jepg', '.JPEG']
# 图片总数
global g_pic_num
g_pic_num = 0
# 压缩图片数量
global g_compress_pic_num
g_compress_pic_num = 0
max_size = 50
usePngQuantAndImageMagickAPI(max_size)
print (u'总共图片大小:{0}KB 压缩了:{1}KB 压缩后大小:{2}KB'
.format(g_total, g_compress_size, (g_total - g_compress_size)))
print (u'图片总数:{0}张 压缩图片数:{1}张'.format(g_pic_num, g_compress_pic_num))
time2 = time.time()
print u'总共耗时:' + str(time2 - time1) + 's'
我的项目运行后:
总共图片大小:29232.0KB 压缩了:14152.0KB 压缩后大小:15080.0KB
图片总数:759张 压缩图片数:94张
总共耗时:42.7580001354s
参数还可再调整下,现在还凑合。
总结:网上的轮子很多,仔细找找,总有一款合适你的需求。但要成为大牛,还是自己实现一遍比较diao。
再分享个技巧:找不到合适的方法时,可以下载类似软件,看下它们的库文件。就像ImageMagick,我是下载搜索排行第一的压缩宝,才找到的。/手动斜眼笑