在Python中检查图像格式是否为无损吗?
我正在开发一个应用程序,需要提交的图片是无损的。目前,我是用PIL这个库打开图片,然后检查它的“格式”属性是否是无损格式。这就意味着我得手动维护一个格式列表,而且我不知道,比如说,提交的jpeg图片是否恰好是无损版本。
import PIL
import PIL.Image
def validate_image(path):
img = PIL.Image.open(path)
if not img.format.lower() in ['bmp', 'gif', 'png', ...]:
raise Exception("File %s has invalid image format %s" % (path, img.format))
有没有更好的方法来检查图片文件是否是无损的呢?
1 个回答
我想我现在明白了:你想通过PIL打开图片。你想拒绝那些有损失的数据的图片,因为你在做某种科学处理,需要保留所有丢失的数据,因为对人眼来说不重要的信息,对你的算法却很重要。
PIL在顶层并没有提供区分不同压缩类型的接口。你可以深入到图片解码器里,假设使用“原始”解码器的图片是无损的,但即使你想这么做,这也太有限了——这样会排除GIF、LZW压缩的TIFF等格式,还有JPEG、JPEG压缩的TIFF等。
要记住,真正的问题在于信息传达和文档管理——也就是管理用户的期望。检查有损失的图片其实只是一个经验法则,用来捕捉一些明显的错误,并提醒用户要求是什么。所以,你不需要完美的解决方案,但有一个相对不错的方案可能还是有帮助的。
所以,选项不多,且都不是很好:
修改PIL的解码器源代码,以保留编码信息并传递到顶层。这显然需要不少工作,涉及到30个不同的导入器,可能还需要用到C和Python,并且你会得到一个补丁,需要在不断变化的代码库中维护——当然,你可以把它提交上去,希望能在未来的PIL版本中实现。
深入解码器本身,在运行时获取信息。你能找到的唯一半标准的东西就是它们是否使用原始解码器或位解码器,但这并没有什么用(很多无损格式需要位解码器),所以你可能最终会阅读所有30个导入器,并写十几段代码来提取信息。
使用其他库,和PIL一起使用(或替代PIL)。例如,虽然ImageMagick并不比PIL简单得多,但它确实有一个API可以告诉你图片文件使用了什么类型的压缩。基本上,如果是
UndefinedCompression
或JPEGCompression
就是有损的,其他的就是无损的。主要的缺点(除了需要安装两个图像库)是,有些文件PIL可以打开,但IM不能,反之亦然,还有多图像文件PIL和IM处理方式不同,等等。继续你现在的做法。查看这30个导入器,列出哪些是有损的,哪些是无损的。为了处理像JPEG和TIFF这样的有时是无损的情况,你可能想写代码,不直接拒绝它们,而是给出一个警告,提示“这些文件可能是有损的。你确定要导入吗?”(或者,提供一个“我知道我在做什么”的选项,针对所有有损格式,然后就把JPEG和TIFF视为有损的。)
对于很多使用场景,我会对选择第4个选项非常谨慎,但对于你的情况,这似乎是相当合理的。你并不是因为代码会崩溃,或者出于安全原因,想要阻止有损图片;你只是想警告人们,如果他们提交JPEG,会浪费很多时间得到无用的信息,对吧?