关于python:如何检查文件是否是有效的图像文件?

How to check if a file is a valid image file?

我目前正在使用PIL。

1
2
3
4
5
6
from PIL import Image
try:
    im=Image.open(filename)
    # do stuff
except IOError:
    # filename not an image file

然而,虽然这足以覆盖大多数情况,但一些图像文件,如xcf、svg和psd没有被检测到。PSD文件引发溢出错误异常。

有什么办法可以把它们也包括进来吗?


我刚找到内置imghdr模块。从python文档:

The imghdr module determines the type
of image contained in a file or byte
stream.

这就是它的工作原理:

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

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


除了Brian建议的以外,您还可以使用pil的verify方法检查文件是否被破坏。

im.verify()

Attempts to determine if the file is
broken, without actually decoding the
image data. If this method finds any
problems, it raises suitable
exceptions. This method only works on
a newly opened image; if the image has
already been loaded, the result is
undefined. Also, if you need to load
the image after using this method, you
must reopen the image file. Attributes


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


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


在Linux上,可以使用python magic(http://pypi.python.org/pypi/python magic/0.1),它使用libmagic来标识文件格式。

LibMagic会查看文件,并试图告诉您更多关于它的信息,而不仅仅是格式,如位图尺寸、格式版本等。所以你可能会认为这是对"有效性"的一个肤浅的测试。

对于"有效"的其他定义,您可能需要编写自己的测试。


嗯,我不知道PSD的内部结构,但是我,当然,我知道,事实上,SVG本身不是一个图像文件,它是基于XML的,所以它本质上是一个纯文本文件。


更新

我还在Github上的python脚本中实现了以下解决方案。

我还验证了损坏的文件(JPG)通常不是"损坏的"图像,即损坏的图片文件有时仍然是合法的图片文件,原始图像丢失或更改,但您仍然可以加载它而不会出错。但是,文件截断总是会导致错误。

结束更新

您可以使用大多数图像格式的python-bellow(pil)模块来检查文件是否是有效且完整的图像文件。

如果您的目标是检测也被破坏的图像,@nadia alramli正确地建议使用im.verify()方法,但这并不能检测所有可能的图像缺陷,例如im.verify不检测被截断的图像(大多数观众通常使用灰色区域加载)。

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

1
2
3
4
5
6
7
8
9
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(PIL.Image.FLIP_LEFT_RIGHT)
  im.close()
except:
  #manage excetions here

如果出现图像缺陷,此代码将引发异常。请考虑im.verify比执行图像操作快100倍(我认为flip是更便宜的转换之一)。使用此代码,您将使用标准枕头以大约10兆字节/秒的速度验证一组图像,或使用枕头SIMD模块(现代2.5GHz x86_64 CPU)以40兆字节/秒的速度验证一组图像。

对于其他格式PSD、XCF等。您可以使用ImageMagick包装棒,代码如下:

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

但是,从我的实验中,魔杖并没有检测到截短的图像,我认为它在没有提示的情况下将缺少的部分加载为灰色区域。

我知道imagemagick有一个外部命令identify,它可以生成该作业,但是我没有找到一种以编程方式调用该函数的方法,我也没有测试过这个路由。

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

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

检查文件扩展名是可以接受的还是试图确认数据本身是否代表图像文件?

如果可以检查文件扩展名,则正则表达式或简单的比较可以满足要求。