PIL Image 操作是出现如下错误:
image file is truncated (2 bytes not processed)
其原因是图像文件损坏,导致 Image 无法处理.
1. 问题分析
示例图片 - test.jpg
如下,
from PIL import Image
from io import BytesIO
#正常图片
with open('test.jpg', 'rb') as fp:
img_bytes = fp.read() #'b'二进制读取
img_pil = Image.open(BytesIO(img_bytes))
img_pil.show()
#损坏图片
truncated_img_bytes = img_bytes.replace(b'\xff\xd9', b'')
truncated_img_pil = Image.open(BytesIO(truncated_img_bytes))
truncated_img_pil.show() #报错
#损坏图片字节写入文件.
with open('truncated_test.jpg', 'wb') as fp:
fp.write(truncated_img_bytes)
正常图片编码:
SOI,Start of Image,图像开始标记:2字节,固定值\xff\xd8
EOI,End of Image,图像结束标记:2字节,固定值\xff\xd9
即,正常图片的字节流是以 \xff\xd8
开始,\xff\xd9
结束.
如果图片损坏,结束处字节将不是 \xff\xd9
.
2. 解决方案
在实际场景中,解决方案有三种:
[1] - 直接本地删除损坏图片(不影响的情况下)
[2] - 添加如下代码,跳过损坏图片的处理:
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
#当遇到数据截断的图片时,PIL会直接break,跳出函数,不报错,进行下一个
[3] - 如果损坏的图片数据影响不大时,可以进行数据字节信息补全:
with open('test.jpg', 'rb') as fp:
img_bytes = fp.read() #'b'二进制读取
if not img_bytes.endswith(b'\xff\xd9'):
img_bytes = img_bytes + b'\xff\xd9'