一、项目需求
图片太大,导致word文档占用太多内存卡死,需要通过压缩来减小文件的体积。
二、python实现代码
以下代码用于批量压缩png/jpg格式的图片文件,遇到报错就使用pip大法安装一下对应的类库就可以了。
dynamic_quality.py
import PIL.Image
from math import log
from SSIM_PIL import compare_ssim
def get_ssim_at_quality(photo, quality):
"""Return the ssim for this JPEG image saved at the specified quality"""
ssim_photo = "tmp.jpg"
photo.save(ssim_photo, format="JPEG", quality=quality, progressive=True)
ssim_score = compare_ssim(photo, PIL.Image.open(ssim_photo))
return ssim_score
def _ssim_iteration_count(lo, hi):
"""Return the depth of the binary search tree for this range"""
if lo >= hi:
return 0
else:
return int(log(hi - lo, 2)) + 1
def jpeg_dynamic_quality(original_photo):
"""Return an integer representing the quality that this JPEG image should be
saved at to attain the quality threshold specified for this photo class.
Args:
original_photo - a prepared PIL JPEG image (only JPEG is supported)
"""
ssim_goal = 0.9
hi = 35
lo = 30
photo = original_photo.resize((200, 200))
normalized_ssim = get_ssim_at_quality(photo, 10)
selected_quality = selected_ssim = None
for i in range(_ssim_iteration_count(lo, hi)):
curr_quality = (lo + hi) // 2
curr_ssim = get_ssim_at_quality(photo, curr_quality)
ssim_ratio = curr_ssim / normalized_ssim
if ssim_ratio >= ssim_goal:
selected_quality = curr_quality
selected_ssim = curr_ssim
hi = curr_quality
else:
lo = curr_quality
if selected_quality:
return selected_quality, selected_ssim
else:
default_ssim = get_ssim_at_quality(photo, hi)
return hi, default_ssim
cpressJPG.py
from PIL import Image
import dynamic_quality
def compress(filename,originpath,targetpath):
name = filename.rstrip('.png').rstrip('.jpg')
im = Image.open(originpath+filename)
im = im.convert('RGB')
im.format = "JPEG"
new_photo = im.copy()
new_photo.thumbnail(im.size,resample=Image.ANTIALIAS)
save_args = {'format':im.format}
save_args['quality'],value=dynamic_quality.jpeg_dynamic_quality(im)
save_args['optimize']=True
save_args['progressive=True']=True
new_photo.save(targetpath+name+".jpg",**save_args)
if __name__ == '__main__':
import os
originpath = "./images/png/"
targetpath = "./images/test/"
for root, dirs, files in os.walk(originpath):
for file in files:
compress(file,originpath,targetpath)
三、实现效果
压缩之前1176KB: 压缩之后54KB: 最终的图片结果是差不多的: 再细致一点,我们比较jpg压缩前后的大小如下,可以得出以下结论: 从png格式转换到jpg格式,大小压缩了10倍; 降低jpg格式前后,大小压缩了3倍;
四、参考文献
1.使用python对图片进行批量压缩 https://zhuanlan.zhihu.com/p/161274600
|