使用PIL进行图片格式与尺寸转换
现实世界中,图片是经常需要处理的二进制文件类型。从计算机发展的历史来看,图片的格式丰富多彩,但大体来说分成两类:
•位图格式
•矢量格式
矢量格式如svg等,能够随意放大缩小而不变形,原因在于矢量格式描述了如何产生图形的方法。而位图格式(例如BMP/JPEG/PNG等)则指定像素空间大小,并且用不同方法描述了每个点的属性,从而能够保存与恢复图片信息。由于矢量格式与位图格式的内容很丰富,而本系列只是借用工具进行实用化操作,因此不对原理进行深入的讲解。以下代码展示了如何进行多种位图格式的转换。
from PIL import Image
def convert(inputfilename, outputfilename):
im = Image.open(inputfilename)
print(im.format, im.size, im.mode)
im.save(outputfilename)
sourceimage = r'd:\test\girl.png'
targetimages = [r'd:\test\demo.jpg',r'd:\test\demo.bmp',r'd:\test\demo.gif',r'd:\test\demo.webp']
for target in targetimages:
convert(sourceimage,target)
从转换结果来看,bmp格式图片体积最大,jpg格式图片体积最小。原因也很简单,jpg格式是JPEG联合图像专家组定义的一种用于连续色调静态图像压缩的标准。JPEG是一种很灵活的格式,具有调节图像质量的功能,它允许用不同的压缩比例对文件进行压缩,支持多种压缩级别。
在上述代码中,除了常见的图片格式外,还有一种新的图片格式专为web应用而生,这就是webp格式。它能够大大提高网站访问速度,同样的分辨率,大小比 jpg、png小25%以上。在Chrome、Firefox、Edge、Opera等主流浏览器上均获得支持。由于此格式较新,还有许多传统的图片处理工具无法识别,可以使用上述代码将webp与png格式进行相互转换。
在上述代码中,使用了著名的PIL图像处理库。PIL(Python Imaging Library)是一个免费的Python编程语言库。Pillow是一个积极开发的PIL分支,它更易于安装,可在所有主流操作系统上运行,并支持Python 3。该库包含基本图像处理功能。其中格式转换是它的重要功能之一。对于python程序来说,pillow在后,各种所谓的万能格式转化器就直接可以扔了。
svg转png格式
虽然pillow非常强悍,但还是有一些格式是连pillow都处理不了的,例如svg格式。svg是一种开放标准的矢量图形语言,是可缩放的矢量图形格式。svg格式的图像可任意放大图形显示,而且边缘异常清晰,生成的文件很小,方便传输,文字在svg图像中保留可编辑和可搜寻的状态,没有字体的限制,所以十分适合用于设计高分辨率的Web图形页面。以下代码展示了svg这种矢量格式转为位图格式的过程。
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM,renderPS
def svg2png(svgfile,outputfile):
"""
对图片格式进行转换
Args:
svgfile (string): 源图片
outputfile (string): 目标图片
"""
# 打开图片并赋值一份新的图片
img = svg2rlg(svgfile)
renderPM.drawToFile(img, outputfile, fmt="PNG")
svg2png(r'D:\test\logo.svg',r'D:\test\logo.png')
visio图转png
Microsoft Visio是Windows操作系统下运行的流程图和矢量绘图软件,它是Microsoft Office软件的一个部分。2000年微软公司收购同名公司后,Visio成为微软公司的产品。它的竞争者是Adobe Illustrator、Macromedia FreeHand和CorelDraw。Visio虽然是Microsoft Office软件的一个部分。但通常以单独形式出售,并不捆绑于Microsoft Office套装中。它的功能极为强悍,能够无缝与word/excel/ppt融合。在跨平台应用时,有将visio图转换成为PNG格式的需求,以下代码演示了如何做到这些。
import win32com.client as win32
def convert(visiofile):
"""
对图片格式进行转换
Args:
visiofile (string): 源图片
outputfile (string): 目标图片
"""
doc_app = win32.gencache.EnsureDispatch("Visio.Application")
doc = doc_app.Documents.Open(visiofile)
for page in doc.Pages:
page.Export (r"d:\test\%s.png"%(page.Name))
doc.Close()
doc_app.Quit()
convert(r'D:\test\神经元结构.vsd')
上述第三库的安装过程如下所示。
python.exe -m pip install --upgrade pip
# 安装pillow
pip install --upgrade Pillow
# 安装svg相关处理库
pip install svglib
pip install reportlab
# 安装pywin32com
pip install pywin32
缩小图片到指定大小
由于网站的存储与处理能力有限,经常会要求我们上传图片时不能够超过指定大小(例如2M等),非常麻烦。以前笔者也是临时找某些工具软件加工一下,但当手头没有工具软件时就抓狂了。其实,使用python能够非常轻松的完成。
from PIL import Image
import math
def resize2(inputfilename, outputfilename, targetsize=2048):
filestatus = os.stat(inputfilename)
filesize = filestatus.st_size
rate = round(math.sqrt((filesize/1024)/targetsize))
im = Image.open(inputfilename)
width, height = im.size
bigger = True
count = 0
while bigger:
# 不断的输出,并且判断大小是否合适
out = im.resize((math.floor(width/rate), math.floor(height/rate)))
out.save(outputfilename)
# 判断输出文件尺寸是否达标
fs = os.stat(outputfilename)
if fs.st_size/1024 < targetsize:
bigger = False
else:
rate += 0.01
count += 1
print(f'{count} times')
sourceimage = r'd:\test\gallery.png'
targetimage = r'd:\test\gallery-small.png'
resize2(sourceimage, targetimage,targetsize= 2048)
上述代码中缺省大小是2M,可以自行调整。今后上传身份证,各类扫描件等就不犯愁了。