如何检查文件是否是有效的图像文件?

我目前正在使用 PIL。

from PIL import Image
try:
im=Image.open(filename)
# do stuff
except IOError:
# filename not an image file

但是,尽管这足以涵盖大多数情况,但是没有检测到一些图像文件,如 xcf、 svg 和 psd。Psd 文件抛出 Overflow Error 异常。

我能把它们也包括进来吗?

166858 次浏览

很多时候,前两个字符对于各种文件格式来说都是一个神奇的数字。除了上面的异常检查之外,您还可以检查这一点。

在 Linux 上,您可以使用使用 自由魔法蟒蛇魔法来识别文件格式。

AFAIK,libmagic 查看文件并试图告诉你更多关于它的信息,而不仅仅是格式,比如位图尺寸、格式版本等等。因此,你可能会把这看作是对“有效性”的肤浅测试。

对于“有效”的其他定义,您可能必须编写自己的测试。

除了 Brian 建议的,你可以使用 PIL 的 核实方法来检查文件是否破损。

确认

尝试确定文件是否为 没有实际解码 图像数据。如果此方法找到任何 问题,它提出了适当的 此方法仅在 新打开的图像; 如果图像有 已经加载,结果是 还有,如果你需要加载 使用这个方法后,你的图像 必须重新打开图像文件

您可以使用 Python 绑定到 libmagic、 蟒蛇魔法,然后检查 mime 类型。这不会告诉您文件是否损坏或完整,但它应该能够确定它是什么类型的图像。

我刚刚发现了内置的 Imghdr模块:

Imghdr 模块确定类型 包含在文件或字节中的图像 溪流。

事情是这样的:

>>> import imghdr
>>> imghdr.what('/tmp/bass')
'gif'

使用模块比重新实现类似的功能要好得多

更新: < a href = “ https://peps.python.org/pep-0594/# imghdr”rel = “ nofollow noReferrer”> imghdr 在 python 3.11中被弃用

更新

我还在 Python 脚本 在 GitHub 上中实现了以下解决方案。

我还验证了损坏的文件(jpg)通常不是“坏”的图像,也就是说,一个损坏的图片文件有时仍然是一个合法的图片文件,原始图片丢失或更改,但你仍然能够加载它没有错误。但是,文件截断总是会导致错误。

最后更新

您可以使用 Python枕头(PIL)模块(包含大多数图像格式)来检查文件是否是有效的、完整的图像文件。

如果你的目标是检测破碎的图像,@Nadia Alramli 正确地建议使用 im.verify()方法,但是这个 不能检测出所有可能的图像缺陷,例如,im.verify不检测截断的图像(大多数观看者经常加载灰色区域)。

Pillow 也能够检测这些类型的缺陷,但是你必须进行图像处理或图像解码/重编码,或者触发检查。最后,我建议使用以下代码:

from PIL import Image


try:
im = Image.load(filename)
im.verify() #I perform also verify, don't know if he sees other types o defects
im.close() #reload is necessary in my case
im = Image.load(filename)
im.transpose(Image.FLIP_LEFT_RIGHT)
im.close()
except:
#manage excetions here

在图像缺陷的情况下,这段代码将引发一个异常。 请考虑一下,im.ify 比执行图像处理要快100倍(我认为翻转是比较便宜的转换之一)。 使用这段代码,您将使用标准枕头以大约10MBytes/sec 的速度验证一组图像,或使用枕头 SIMD 模块(现代2.5 Ghz x86 _ 64 CPU)以40MBytes/sec 的速度验证一组图像。

对于其他格式的 Xcf,. . 可以使用 想象力包装器 魔杖,代码如下: 检查 Wand 文档: 给你,到安装: < a href = “ https://pypi.org/project/Wand/”rel = “ nofollow norefrer”> 这里

im = wand.image.Image(filename=filename)
temp = im.flip;
im.close()

但是,从我的实验魔杖不检测截断的图像,我认为它加载没有部分作为灰色地区没有提示。

我红色表示 想象力有一个外部命令 确认身份,由 可以执行这个任务,但是我还没有找到一种方法来以编程方式调用这个函数,我也没有测试这个路由。

我建议总是进行初步检查,检查 文件大小是否为零(或非常小) ,这是一个非常 便宜的想法:

import os


statfile = os.stat(filename)
filesize = statfile.st_size
if filesize == 0:
#manage here the 'faulty image' case

除了 PIL映像检查之外,你还可以像下面这样添加文件扩展名检查:

filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))

注意,这只是检查文件名是否有一个有效的图像扩展名,它实际上并没有打开图像来查看它是否是一个有效的图像,这就是为什么你需要额外使用 PIL或其他答案中建议的库之一。

format = [".jpg",".png",".jpeg"]
for (path,dirs,files) in os.walk(path):
for file in files:
if file.endswith(tuple(format)):
print(path)
print ("Valid",file)
else:
print(path)
print("InValid",file)

一种选择是使用 filetype包。

安装

python -m pip install filetype

好处

  1. Fast: 通过加载图像的前几个字节(看看那个神奇的数字)完成工作
  2. 支持不同的哑剧类型: 图像,视频,字体,音频,档案。

例子

Filetype > = 1.0.7

import filetype


filename = "/path/to/file.jpg"


if filetype.is_image(filename):
print(f"{filename} is a valid image...")
elif filetype.is_video(filename):
print(f"{filename} is a valid video...")

Filetype < = 1.0.6

import filetype


filename = "/path/to/file.jpg"


if filetype.image(filename):
print(f"{filename} is a valid image...")
elif filetype.video(filename):
print(f"{filename} is a valid video...")

关于正式回购的补充资料: https://github.com/h2non/filetype.py

改编自法比亚诺和蒂亚戈的答案。

from PIL import Image


def check_img(filename):
try:
im = Image.open(filename)
im.verify()
im.close()
im = Image.open(filename)
im.transpose(Image.FLIP_LEFT_RIGHT)
im.close()
return True
except:
print(filename,'corrupted')
return False


if not check_img('/dir/image'):
print('do something')