Python办公20:图片格式转换——Webp/PNG/JPG 批量互转及无损压缩
2026/9/6 0:43:01 网站建设 项目流程

20:图片格式转换——Webp/PNG/JPG 批量互转及无损压缩

第三阶段:PDF 与图片处理(16-22)

场景引入

  • 网站需要 WebP 格式的图片以提升加载速度
  • 客户要求 JPG 格式方便查看
  • 系统只接受 PNG 格式的图标
  • 图片太大,需要压缩后发送

手动用画图工具一张一张转换?太慢了。本节用 Python 实现批量格式转换和压缩。


技术原理

Pillow 支持几乎所有常见图片格式:

读取图片(任意格式) → PIL Image 对象 → 保存为指定格式
格式特点适用场景
JPG/JPEG有损压缩,不支持透明照片、产品图
PNG无损压缩,支持透明图标、截图
WebPGoogle 格式,体积小网页图片
BMP无压缩老系统兼容
TIFF无损,支持多层印刷、存档

环境准备

pipinstallPillow

完整代码

importosfrompathlibimportPathfromPILimportImage# 支持的图片格式SUPPORTED_EXTENSIONS={'.jpg','.jpeg','.png','.webp','.bmp','.tiff','.gif'}# ==================== 方案 1:单个格式转换 ====================defconvert_image(input_file,output_format='jpg',quality=85,max_size=None):""" 转换图片格式 参数: input_file: 输入图片路径 output_format: 输出格式 'jpg'/'png'/'webp'/'bmp' quality: 压缩质量(1-100,仅对 jpg/webp 有效) max_size: 最大尺寸 (width, height) 或 None """input_path=Path(input_file)img=Image.open(input_path)# 如果需要调整大小ifmax_size:img.thumbnail(max_size,Image.LANCZOS)# 处理 RGBA → RGB(JPG 不支持透明通道)ifoutput_formatin('jpg','jpeg','bmp')andimg.mode=='RGBA':# 白色背景替代透明background=Image.new('RGB',img.size,(255,255,255))background.paste(img,mask=img.split()[3])img=background# 生成输出文件名output_file=input_path.with_suffix(f'.{output_format}')# 保存参数save_kwargs={}ifoutput_formatin('jpg','jpeg'):save_kwargs={'quality':quality,'optimize':True}elifoutput_format=='webp':save_kwargs={'quality':quality,'method':6}elifoutput_format=='png':save_kwargs={'optimize':True}img.save(output_file,**save_kwargs)# 打印对比original_size=input_path.stat().st_size new_size=output_file.stat().st_size ratio=(1-new_size/original_size)*100print(f"{input_path.name}({original_size/1024:.1f}KB) → "f"{output_file.name}({new_size/1024:.1f}KB) "f"[{'+'ifratio<0else'-'}{abs(ratio):.1f}%]")returnoutput_file# ==================== 方案 2:批量转换 ====================defbatch_convert_folder(input_dir,output_dir,output_format='jpg',quality=85):""" 批量转换文件夹中的所有图片 """input_path=Path(input_dir)output_path=Path(output_dir)output_path.mkdir(parents=True,exist_ok=True)count=0total_saved=0forfile_pathininput_path.iterdir():iffile_path.is_file()andfile_path.suffix.lower()inSUPPORTED_EXTENSIONS:output_file=output_path/f"{file_path.stem}.{output_format}"img=Image.open(file_path)original_size=file_path.stat().st_size# 处理 RGBA → RGBifoutput_formatin('jpg','jpeg','bmp')andimg.mode=='RGBA':background=Image.new('RGB',img.size,(255,255,255))background.paste(img,mask=img.split()[3])img=background save_kwargs={}ifoutput_formatin('jpg','jpeg'):save_kwargs={'quality':quality,'optimize':True}elifoutput_format=='webp':save_kwargs={'quality':quality,'method':6}img.save(output_file,**save_kwargs)new_size=output_file.stat().st_size total_saved+=original_size-new_size count+=1print(f"\n批量转换完成:{count}张图片")print(f"节省空间:{total_saved/1024/1024:.2f}MB")# ==================== 方案 3:批量压缩(不改变格式) ====================defbatch_compress_images(input_dir,output_dir,quality=75,max_width=1920,max_height=1080):""" 批量压缩图片(保持原格式,降低质量和尺寸) """input_path=Path(input_dir)output_path=Path(output_dir)output_path.mkdir(parents=True,exist_ok=True)count=0total_saved=0forfile_pathininput_path.iterdir():iffile_path.is_file()andfile_path.suffix.lower()in{'.jpg','.jpeg','.png','.webp'}:img=Image.open(file_path)# 缩小尺寸ifmax_widthandmax_height:img.thumbnail((max_width,max_height),Image.LANCZOS)save_kwargs={}iffile_path.suffix.lower()in('.jpg','.jpeg'):save_kwargs={'quality':quality,'optimize':True}output_file=output_path/file_path.name img.save(output_file,**save_kwargs)original_size=file_path.stat().st_size new_size=output_file.stat().st_size total_saved+=original_size-new_size count+=1print(f"批量压缩完成:{count}张图片")print(f"节省空间:{total_saved/1024/1024:.2f}MB")# ==================== 使用示例 ====================if__name__=="__main__":# 单个转换# convert_image("photo.png", output_format='jpg', quality=85)# 批量转 WebP(网页优化)batch_convert_folder("产品图片","产品图片_WebP",output_format='webp',quality=80)# 批量压缩# batch_compress_images("原始照片", "压缩照片", quality=75, max_width=1920)

常见问题

Q1:GIF 动图转换后不动了?

Pillow默认只读取 GIF 的第一帧。如需保留动画,使用imageio

pipinstallimageio
importimageio frames=imageio.mimread('animation.gif')imageio.mimwrite('output.webp',frames,duration=0.1)

Q2:JPG 转 PNG 后体积变大很多?

JPG 是有损压缩,PNG 是无损压缩。JPG → PNG 会"放大"原本被压缩的信息。建议反向转换(PNG → JPG)来减小体积。


总结

操作方法效果
格式转换img.save('output.jpg')自动转换
压缩质量quality=75降低文件大小
缩小尺寸img.thumbnail()等比例缩放
透明处理RGBA → RGBJPG 兼容

本节掌握了图片格式批量转换和压缩的能力。

下一节预告:21:表格提取——从 PDF 扫描件中自动抓取表格数据至 Excel!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询