PIL.Image.open() 返回的对象立即提供 size 和 mode 属性,无需 .load();size 是 (width, height) 像素元组,mode 表示色彩空间(如 'RGB'、'RGBA');AttributeError 通常因对象未正确创建或提前关闭导致。

用 PIL.Image.open() 读取图片后直接查 size 和 mode
图片分辨率和色彩格式不是“额外提取”的元数据,而是打开后立刻可得的实例属性。只要不调用 .load() 或 .convert() 等触发解码的操作,size(宽高元组)和 mode(如 'RGB'、'L'、'RGBA')在 Image.open() 返回对象上就已就绪。
常见错误是以为要先 .load() 才能读尺寸——其实完全没必要,反而可能触发不必要的解码,尤其对大图或 WebP/HEIC 等格式。
-
size是(width, height)元组,单位为像素,始终存在 -
mode表示色彩空间和通道数:'1'(1-bit)、'L'(灰度)、'RGB'(三通道)、'RGBA'(带 Alpha)、'CMYK'(印刷)等 - 某些格式(如 JPEG)即使保存时带 ICC 配置文件,
mode也不会变成'RGBX'或其他变体,仍是'RGB'
遇到 AttributeError: 'JpegImageFile' object has no attribute 'size' 怎么办
这说明你没真正拿到 Image 对象,而是误用了未完成加载的句柄,或者对象已被关闭。典型场景是:用 with open(...) 打开文件但没传给 PIL.Image.open(),或在 with Image.open(...) as img: 块外访问 img。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 正确做法:始终用
img = Image.open(path_or_file),且确保path_or_file是有效路径或 file-like 对象 - 如果从字节流读取(如 requests 响应),必须用
io.BytesIO(resp.content)包一层再传给Image.open(),不能直接传resp.content - 不要对
Image.open()的返回值做del或提前.close(),否则后续访问size会失败
mode 值和实际像素数据不一定一致
mode 是 PIL 内部解释的色彩模式,不等于原始文件存储格式。比如一张 8-bit 灰度 PNG,mode 是 'L';但若用 .convert('RGB'),mode 就变成 'RGB',哪怕像素值全是 (x,x,x)。更隐蔽的是:某些 JPEG 文件带 Exif Orientation,size 返回的是“逻辑尺寸”,而原始 JPEG 数据可能是旋转前的宽高。
- 想确认真实编码格式?看文件头或用
file命令,PIL 的mode不反映容器格式(如 JPEG vs PNG) - 处理 WebP 或 AVIF 时,
mode可能是'RGB'或'RGBA',但底层压缩方式完全不影响mode值 - 用
img.getbands()查通道名(如('R', 'G', 'B')),比只看mode更直观
需要 EXIF、DPI、ICC 等扩展信息时别依赖 size/mode
size 和 mode 是图像数据的基本描述,不包含拍摄时间、设备型号、物理分辨率(DPI)或色彩配置文件。这些属于元数据,需单独提取,且不同格式支持程度差异很大。
- JPEG/TIFF 的 EXIF 和 IPTC 信息可通过
img._getexif()(已弃用)或img.info.get('exif')+PIL.ExifTags解析,但结构复杂、字段不统一 - DPI 存在
img.info中,键名可能是'dpi'(元组)或'jfif_density',且很多编辑器会丢弃它 - ICC 配置文件在
img.info.get('icc_profile'),但长度可能达几百 KB,且 PIL 不校验其有效性 - 别试图从
mode推断是否含透明通道:用'A' in img.getbands()更可靠
PIL 的 size 和 mode 看似简单,但容易混淆“解码后视图”和“原始文件语义”。真要靠住,得盯紧对象生命周期、区分容器格式与色彩模式、并意识到元数据永远是另一套体系。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










