如何将大量JPG图片转为Web优化的极小体积PDF?
图片转小体积PDF优化方案
问题背景
有2000张单张约150KB、96dpi的图片,需转换为体积尽可能小的PDF,但使用PyPDF2生成的PDF体积超大(约800000MB),原代码如下:
for i in range(0, noImages): image = Image.open(newimageList[i]) if(i == 0): image.save(namePath, "PDF" ,quality=100, optimize=True, save_all=True) else: namePath2 = rootPDF+pdf_id+"temp.pdf" image.save(namePath2, "PDF" ,quality=100, optimize=True, save_all=True) pdfs = [namePath, namePath2] merger = PdfFileMerger() for f in pdfs: merger.append(PdfFileReader(f), 'rb') with open(namePath, 'wb') as new_file: merger.write(new_file) os.remove(namePath2)
问题分析
原代码的核心问题:
- 每次循环都合并PDF,反复写入会产生大量冗余数据,导致体积暴增
- 保存PDF时设置
quality=100,几乎没有对图片进行压缩 - 未处理带透明通道的图片(如PNG),这类图片转PDF时会额外占用空间
优化方案
1. 一次性批量生成PDF(最核心优化)
直接加载所有图片后一次性保存,避免反复合并操作,同时调整压缩参数:
from PIL import Image import os # 批量加载并处理图片 processed_images = [] for img_path in newimageList: img = Image.open(img_path) # 将带透明通道的图片转为RGB格式 if img.mode in ('RGBA', 'P'): img = img.convert('RGB') processed_images.append(img) # 一次性生成PDF if processed_images: processed_images[0].save( namePath, format="PDF", quality=60, # 可根据需求调整,50-70区间兼顾体积和清晰度 optimize=True, save_all=True, append_images=processed_images[1:] # 直接追加所有后续图片 )
2. 先压缩图片再转PDF(进一步减小体积)
如果图片仍有压缩空间,可先对图片进行分辨率和质量压缩:
from PIL import Image import os def process_image(img_path, target_quality=60, target_dpi=96): img = Image.open(img_path) # 转换为RGB格式 if img.mode in ('RGBA', 'P'): img = img.convert('RGB') # 统一设置分辨率 img.info['dpi'] = (target_dpi, target_dpi) return img # 处理所有图片 processed_images = [process_image(path) for path in newimageList] # 生成PDF if processed_images: processed_images[0].save( namePath, format="PDF", quality=target_quality, optimize=True, save_all=True, append_images=processed_images[1:] )
3. 用PyMuPDF二次压缩PDF(可选)
如果生成的PDF体积仍不符合预期,可使用PyMuPDF对成品PDF进一步压缩:
import fitz def compress_pdf(input_pdf, output_pdf): doc = fitz.open(input_pdf) # 遍历每页压缩图片 for page in doc: pix = page.get_pixmap() # 设置分辨率为96dpi,图片质量60 pix.set_dpi(96, 96) pix.save("temp_img.jpg", quality=60) # 替换页内图片 page.insert_image(page.rect, filename="temp_img.jpg") # 保存压缩后的PDF,启用垃圾回收和压缩 doc.save(output_pdf, garbage=4, deflate=True) doc.close() os.remove("temp_img.jpg") # 调用示例:先生成PDF,再压缩 compress_pdf(namePath, f"compressed_{namePath}")
关键优化点总结
- 避免反复合并PDF:一次性追加所有图片,消除冗余数据
- 降低图片质量:
quality=100无压缩,调整到50-70可大幅减小体积 - 处理透明通道图片:转RGB格式避免额外空间占用
- 选择高效工具:PIL批量生成比PyPDF2合并更高效,PyMuPDF压缩能力更强
内容的提问来源于stack exchange,提问作者danielE
相关产品推荐
相关产品推荐

