如何在不提高PIL限制的前提下加载超像素图片并降采样
解决PIL加载大图片触发DecompressionBombError的方案(不提高限制)
问题描述
我有一个图片路径problem_page,执行以下Python代码:
from PIL import Image problem_page = "/home/rajiv/tmp/kd/pss-images/f1-577.jpg" img = Image.open(problem_page)
触发了如下错误:
PIL.Image.DecompressionBombError: Image size (370390741 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
我希望不提高PIL的像素限制,而是通过将图片分辨率降至限制以下的方式加载图片,让img引用低分辨率版本且不触发错误。优先需要Python解决方案,其他方案也可接受。
补充说明
这些图片由PDF转换而来,用于机器学习场景,PDF来自外部系统,因此需要保护系统免受解压炸弹攻击。大多数ML场景对像素尺寸的要求远低于PIL设定的限制,所以我们把这个限制作为保护系统的启发式规则。目前我们的方案是用pdf2image转换PDF为图片时指定像素尺寸(比如width=1700 pixels,height=2200 pixels),但想知道是否能在加载图片时完成这个操作。
Python解决方案(基于PIL)
核心思路是先读取图片元信息(不加载完整像素),计算安全缩放比例后再加载并缩小图片:
from PIL import Image def load_safe_image(image_path, max_pixels=178956970): # 打开图片但不加载像素数据,避免触发错误 with Image.open(image_path) as img: current_pixels = img.width * img.height if current_pixels <= max_pixels: # 像素数符合要求,直接返回图片副本 return img.copy() # 计算等比例缩放因子,确保缩放后总像素不超过限制 scale_factor = (max_pixels / current_pixels) ** 0.5 new_width = int(img.width * scale_factor) new_height = int(img.height * scale_factor) # 按新尺寸缩放图片,LANCZOS滤镜保证缩放质量 return img.resize((new_width, new_height), Image.Resampling.LANCZOS) # 使用示例 problem_page = "/home/rajiv/tmp/kd/pss-images/f1-577.jpg" img = load_safe_image(problem_page)
注意事项
- PIL版本低于9.1.0时,把
Image.Resampling.LANCZOS替换为Image.LANCZOS - 缩放采用等比例方式,避免图片变形,适合机器学习场景的图片输入要求
其他方案(命令行工具)
可以用ImageMagick的convert工具提前压缩图片,再用PIL加载处理后的文件:
convert /home/rajiv/tmp/kd/pss-images/f1-577.jpg -resize @178956970 /path/to/safe_image.jpg
@178956970参数表示限制图片总像素不超过该值,工具会自动按比例缩放- 处理完成后直接用
Image.open()加载/path/to/safe_image.jpg即可
内容的提问来源于stack exchange,提问作者RAbraham
相关产品推荐
相关产品推荐

