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'
Last modification:May 15th, 2021 at 09:31 pm