Vector协议栈如何实现车载无感刷写:从UDS到OTA的关键技术解析
2026/9/6 20:00:21
第三阶段:PDF 与图片处理(16-22)
手动用画图工具一张一张转换?太慢了。本节用 Python 实现批量格式转换和压缩。
Pillow 支持几乎所有常见图片格式:
读取图片(任意格式) → PIL Image 对象 → 保存为指定格式| 格式 | 特点 | 适用场景 |
|---|---|---|
| JPG/JPEG | 有损压缩,不支持透明 | 照片、产品图 |
| PNG | 无损压缩,支持透明 | 图标、截图 |
| WebP | Google 格式,体积小 | 网页图片 |
| BMP | 无压缩 | 老系统兼容 |
| TIFF | 无损,支持多层 | 印刷、存档 |
pipinstallPillowimportosfrompathlibimportPathfromPILimportImage# 支持的图片格式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)Pillow默认只读取 GIF 的第一帧。如需保留动画,使用imageio:
pipinstallimageioimportimageio frames=imageio.mimread('animation.gif')imageio.mimwrite('output.webp',frames,duration=0.1)JPG 是有损压缩,PNG 是无损压缩。JPG → PNG 会"放大"原本被压缩的信息。建议反向转换(PNG → JPG)来减小体积。
| 操作 | 方法 | 效果 |
|---|---|---|
| 格式转换 | img.save('output.jpg') | 自动转换 |
| 压缩质量 | quality=75 | 降低文件大小 |
| 缩小尺寸 | img.thumbnail() | 等比例缩放 |
| 透明处理 | RGBA → RGB | JPG 兼容 |
本节掌握了图片格式批量转换和压缩的能力。
下一节预告:21:表格提取——从 PDF 扫描件中自动抓取表格数据至 Excel!