在之前的博文中写过检测JPEG、PNG图片是否完整,通过结束符的检测能很好的发现图片没有下载完成。如下图的情况。

这种方式过于简单粗暴,其实判断图片到底能不能用,最终的答案是图片中各个字段能不能成功读取。能全部读取的,就可以认为这个是一个好的图片。
再看两个有冗余字段的文件。
![]() | ![]() |
这两个图片的二进制显示,但在图片文件结束的时候,被加入了很多数据。这个时候使用简单的结束符号判断显然不是正确的方法。最好的方法就是读取图片的各个字段。但编写读取字段的代码类似于重复制造车轮,所以我选择了“PIL”,他能很好的解决这个问题,由于效率问题仅仅对没有结束字符的图片进行二次筛查。代码如下:
import os
import shutil
from PIL import Image
DirList = [
'/home/king/PycharmProjects/nsfw_data_scrapper/raw_data/drawings',
'/home/king/PycharmProjects/nsfw_data_scrapper/raw_data/hentai',
'/home/king/PycharmProjects/nsfw_data_scrapper/raw_data/neutral',
'/home/king/PycharmProjects/nsfw_data_scrapper/raw_data/porn',
'/home/king/PycharmProjects/nsfw_data_scrapper/raw_data/sexy'
]
def is_valid_jpg(jpg_file):
with open(jpg_file, 'rb') as f:
f.seek(-2, 2)
buf = f.read()
return buf == b'\xff\xd9'
def is_valid_png(png_file):
with open(png_file, 'rb') as f:
f.seek(-3, 2)
buf = f.read()
if buf == b'\x60\x82\x00':
return True
elif buf[1:] == b'\x60\x82':
return True
else:
return False
def is_valid_pic(pic_file):
if pic_file.endswith('jpeg'):
return is_valid_jpg(pic_file)
elif pic_file.endswith('png'):
return is_valid_png(pic_file)
else:
return False
for path in DirList:
for file in os.listdir(path):
pic_file = os.path.join(path, file)
if not is_valid_pic(pic_file):
try:
img = Image.open(pic_file)
img.load()
except Exception as e:
#print(e)
print(pic_file)
#shutil.copy(pic_file, '/home/king/Desktop/')
#os.remove(pic_file)
最后不完整的图片被打印出来。
网上还有一种方式是 Image.open(file).verify(),但通过这个检测,我发现我有大量大量的图片是不完整的,真的吓到我了。不知道是不是我的版本问题,最后被弃用了。
本文介绍了如何利用Python的PIL库来精确检测JPEG和PNG图片的完整性,通过读取图片的各个字段,而非仅仅依赖于结束符。这种方法能有效处理含有冗余字段的图片,避免误判。


&spm=1001.2101.3001.5002&articleId=90477650&d=1&t=3&u=1f219270c0e8421a9524468210e99a01)
290

被折叠的 条评论
为什么被折叠?



