我正在开发一个应用程序,要求提交给它的图像是无损的。目前,我正在打开带有PIL的图像,并检查“format”属性是否是无损格式。这需要我手动保存一个格式列表,我不知道,例如,提交的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))

有没有更好的方法检查图像文件是否无损?

最佳答案

我想我现在明白了:你想通过PIL打开图片。你想拒绝有损图像是因为你正在进行某种需要所有丢失数据的科学处理,因为对人类视觉处理不重要的信息对你的算法很重要。
PIL在顶层没有任何接口来区分不同类型的压缩。你可以进入图像解码器,并假设任何使用“原始”解码器是无损的,但即使你想这样做,这太有限了,它将排除GIF,LZW压缩TIFF等,连同JPEG,JPEG压缩TIFF等。
请记住,真正的问题在于消息和文档管理用户期望。有损图像的检查实际上只是一种启发,一种捕捉更明显错误并提醒用户需求的方法。所以,你不需要完美的东西,但拥有一些很好的东西可能会有帮助。
所以,只有几个选择,没有一个非常好:
破解PIL的解码器源代码,保留编码信息并将其传递到顶层。显然,这需要在30个不同的导入程序中进行一些非琐碎的工作,可能涉及到C和Python,这将导致一个补丁,您必须针对(缓慢)发展的代码库进行维护,当然,您可以始终将其提交到上游,并希望它能够进入PIL的未来版本。
挖掘解码器本身,以便在运行时获取信息。你能找到的唯一半标准的东西是他们是使用原始解码器还是位解码器,这一点都不有用(许多无损格式需要位解码器),所以你可能最终会阅读所有30个导入程序,并编写十几段代码从中提取信息。
使用另一个库和(或代替)PIL。例如,虽然ImageMagick肯定不会比PIL简单得多,但它确实有一个API来告诉您图像文件使用的压缩类型。基本上,如果它是UndefinedCompressionJPEGCompression它是有损的,其他的,它是无损的。主要的缺点(除了需要安装两个映像库之外)是PIL可以打开但IM不能打开的文件,反之亦然,以及PIL和IM处理不同的多映像文件,等等。
做你已经在做的事。请通读30家进口商的名单,列出哪些是有损的,哪些是无损的。为了处理JPEG和TIFF等有时是无损的情况,您可能需要编写不完全拒绝它们的代码,但会给出警告:“这些文件可能是有损的。您确定要导入它们吗?”(或者,只需为所有有损格式提供一个“我知道我在做什么”覆盖,然后考虑JPEG和TIFF有损格式。)
对于许多用例,我会非常谨慎地使用4,但是对于您的用例,它实际上看起来非常合理。你不是因为你的代码会崩溃,或者出于安全原因,或者诸如此类的原因而试图阻止有损图像;你只是想警告人们,如果他们提交JPEG,他们将浪费大量时间获取无用信息,对吧?

10-07 17:09