如何用PyMuPDF降低PDF中所有图片质量并优化压缩?
用PyMuPDF最大化压缩PDF的解决方案
一、替换页面中的图片并压缩质量
你可以直接在PyMuPDF内完成图片压缩与替换,无需先导出到本地。核心逻辑是遍历页面图片,提取后转低质量JPEG,再替换回原位置。以下是可直接运行的代码:
import fitz # PyMuPDF def compress_pdf_images(input_path, output_path, image_quality=50): doc = fitz.open(input_path) for page_num in range(len(doc)): page = doc[page_num] # 获取页面所有图片的完整信息 image_list = page.get_images(full=True) for img in image_list: xref = img[0] # 图片的唯一引用编号 # 提取原图片数据 base_image = doc.extract_image(xref) img_bytes = base_image["image"] # 将图片转为低质量JPEG temp_doc = fitz.open() temp_page = temp_doc.new_page() temp_page.insert_image(temp_page.rect, stream=img_bytes) # 导出压缩后的JPEG字节流 compressed_jpeg = temp_doc.convert_to_pdf("jpeg", quality=image_quality) temp_doc.close() # 获取原图片在页面上的位置和尺寸 img_rect = page.get_image_rects(xref)[0] # 删除原图片,插入压缩后的新图片 page.delete_image(xref) page.insert_image(img_rect, stream=compressed_jpeg) # 保存时启用全量压缩参数 doc.save( output_path, deflate=True, garbage=4, # 清理所有冗余数据(无效对象、旧版本内容等) clean=True, deflate_images=True, # 额外压缩图片流 deflate_fonts=True, # 压缩嵌入字体流 subset_fonts=True # 子集化嵌入字体(只保留用到的字符) ) doc.close() # 使用示例 compress_pdf_images("input.pdf", "compressed_output.pdf", image_quality=50)
代码说明:
- 用
xref定位页面内的图片对象,确保精准替换 - 通过
convert_to_pdf强制将所有图片转为JPEG格式,quality参数控制压缩程度(数值越小体积越小,画质越低) - 替换时保留原图片的位置和尺寸,避免页面布局混乱
- 保存时叠加多个压缩参数,最大化压缩效果
二、更优的PDF压缩补充技巧
除了图片处理,结合以下操作能进一步缩小文件体积:
- 统一图片格式:将PDF内的PNG、TIFF等无损格式全部转为JPEG,是压缩图片类PDF最有效的方式,上述代码已实现此逻辑
- 降低图片分辨率:如果PDF无需高清显示,可在
insert_image时添加dpi参数(如dpi=50),直接缩小图片像素尺寸 - 清理冗余元素:用
page.delete_annot()移除页面注释,或保存时加sanitize=True清理表单域、脚本等非必要内容 - 调整压缩级别:
deflate=True会压缩所有对象流,若追求极限压缩,可尝试deflate_level=9(最高压缩级别,耗时略长)
内容的提问来源于stack exchange,提问作者Mikhailo
相关产品推荐
相关产品推荐

