PIL.Image 读取多页TIFF需用 seek()/tell() 循环遍历,不可直接 for page in Image.open();应先检查 img.n_frames 或 img.is_animated,每页调用 .copy() 后显式指定 compression 和 mode 保存,避免数据截断与元数据丢失。

用 PIL.Image 读取多页TIFF并遍历保存
Python标准库不支持多页TIFF,必须用 PIL(即 Pillow),它底层调用libtiff处理页帧。直接打开多页TIFF时,Image.open() 只加载第一页;要读取全部页,得用 seek() 和 tell() 配合循环。
常见错误是写成 for page in Image.open("x.tiff") —— 这会报 TypeError: 'PngImageFile' object is not iterable(即使文件是TIFF,对象类型名也可能显示为PngImageFile)。
- 先用
Image.open()打开文件,得到首帧对象 - 用
while True:+try/except EOFError捕获末页异常 - 每页调用
.copy()避免后续seek()影响当前图像数据 - 保存时显式指定
format="TIFF",否则可能被自动转成PNG或丢失TIFF特有元数据
seek() 和 is_animated 判断是否真为多页TIFF
不是所有扩展名为 .tiff 的文件都含多页:有些只是单页+压缩,有些是“fake multi-page”(如Photoshop导出的伪多页)。盲目循环会导致 EOFError 提前抛出或只存一页。
is_animated 属性在 Pillow ≥ 9.0.0 中才稳定支持多页TIFF识别;旧版本需靠捕获 EOFError 或检查 __getattr__("n_frames", 1)。
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 推荐先查
img.n_frames(返回整数页数),若不存在则视为单页 -
img.is_animated为True是更安全的多页信号,但部分扫描仪生成的TIFF可能不设该标志 - 避免依赖文件名或后缀判断——真实场景中常遇到
.tif、.TIF、无后缀的TIFF数据流
保存时控制压缩与色彩模式,防止质量损失
默认 save() 会丢弃原始TIFF的压缩方式(如 LZW、Deflate)和色彩空间(如 minisblack、miniswhite),导致体积暴增或灰度反转。
例如原图是16位灰度LZW压缩TIFF,直接 page.save(f"out_{i}.tiff") 会变成8位无压缩,且可能误转为RGB。
- 用
page.mode检查原始模式:"I;16"、"L"、"RGB"等,保存时传mode=page.mode(注意save()不接受该参数,需用convert()预处理) - 指定压缩:加
compression="tiff_lzw"或"tiff_deflate"(Pillow 9.1+ 支持) - 16位图必须用
img = img.convert("I;16")再保存,否则自动截断为8位 - 避免用
quality=参数——TIFF不支持JPEG式质量控制,该参数会被忽略
批量处理大文件时的内存与路径安全
一页50MB的100页TIFF,全载入内存会吃掉5GB+,seek() 虽不加载全页,但每页 .copy() 仍会复制像素缓冲区。临时文件路径没处理好,还可能覆盖原图。
错误示例:out_path = input_path.replace(".tiff", "_page_{}.tiff") —— 若输入是 /data/a.tiff.bak,就会错删备份文件。
- 用
pathlib.Path解析路径:in_path = Path("scan.tiff"); out_dir = in_path.parent / "split" - 确保
out_dir.mkdir(exist_ok=True),而不是依赖用户提前建目录 - 对超大页(>20MB),改用
ImageOps.grab()截区域再存,或改用tifffile库的内存映射模式(tifffile.memmap()) - 保存前校验目标路径:
if out_path.resolve().parent != out_dir.resolve(): raise ValueError("path escape detected")
多页TIFF的实际结构比表面复杂:页间可能有不同分辨率、不同压缩、不同色彩配置,甚至混合了“图像页”和“标签页”(如EXIF、IPTC)。单纯按序分离只是第一步,后续是否要统一尺寸、对齐坐标、提取元数据,得看下游用途——这些细节往往在第一次保存失败时才暴露出来。

















