【问题标题】:Checking if an image format is Lossless in Python?在 Python 中检查图像格式是否无损?
【发布时间】:2013-02-03 14:29:43
【问题描述】:

我正在开发一个应用程序,该应用程序要求提交给它的图像是无损的。目前我正在使用 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))

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

【问题讨论】:

  • 你必须使用 PIL 吗?例如,使用 PythonMagick,我很确定您可以检查 CompressionType 属性。这是一个更简单的测试——唯一有损的本机压缩类型是JPEGCompression(有损JPEG和TIFF文件使用);对于非本地压缩,您将获得UndefinedCompression,但您可以假设这总是意味着有损。
  • 正如您所指出的,您的代码甚至不起作用,因为无损 JPEG 仍然是 'jpeg',而有损和无损 TIFF 都是 'tiff'。但是让我们退后一步……您的应用程序如何处理提交的图像?它可以处理无损JPEG吗?就此而言,它是否处理 PIL(或 ImageMagick 等)不处理的任何类型,或者不处理 PIL(等)处理的任何类型?因为,如果是这样,仅仅检查“无损”是不够的。
  • 换句话说:为什么你的应用需要无损图片?如果在给定有损图像时它会抛出异常(或 C 或 Java 中的等价物?),那很好;只需将相同的代码(或同一个 C 库的包装器)放在您的前端,如果它失败,您就会知道应用程序将无法处理它,对吗?无论答案是什么,解决方案可能与问题的关系比检查无损性更密切。
  • PIL 最好。如果 PythonMagick 更容易,那么我可以尝试看看是否可以添加它。至于图像格式,我只需要处理那些可以用 PIL 打开的图像 - 图像将被传递到 scipy.misc.fromimage,为应用程序中的所有图像提供单一输入路径(例如 gif,我有直接在 scipy 中打开时注意到的格式不同)。需要无损图像以确保我们收到的数据没有被压缩改变(科学目的)。
  • @GlenNelson 您错误地处理了这个问题。假设有人提交了一个 jpeg(大多数情况下是有损的),然后你的程序设法返回一些内容:“不支持有损图像”。然后用户高兴地继续将他的 jpeg 转换为 png,现在您的程序接受它。你为什么不直接将他的图像转换为 png 并完成它?为什么不在继续之前将每个输入图像转换为常见的无损格式?

标签: python python-imaging-library lossless-compression


【解决方案1】:

我想我现在明白了:您想通过 PIL 打开图像。您想要拒绝有损图像,因为您正在进行某种科学处理,需要所有丢失的数据,因为对人类视觉处理不重要的信息对您的算法很重要。

PIL 在顶层没有任何类型的接口来区分不同类型的压缩。您可以进入图像解码器并假设任何使用“原始”解码器的东西都是无损的,但即使你想这样做,也太有限了——它会排除 GIF、LZW-压缩的 TIFF 等以及 JPEG、JPEG 压缩的 TIFF 等。

请记住,真正的问题在于消息传递和文档——管理用户期望。检查有损图像实际上只是一种启发式方法,一种捕捉更明显错误并提醒用户需求的方法。所以,你不需要完美的东西,但拥有相当好的东西可能会有所帮助。

所以,只有几个选项,都不是很好:

  1. 破解 PIL 的解码器源以保留编码信息并将其传递到顶层。显然,这需要在 30 个不同的导入程序中进行一些重要的工作,可能涉及 C 和 Python,并且它会导致您必须针对(缓慢)发展的代码库维护一个补丁——尽管当然,您可以随时将其提交到上游,并希望它能够成为 PIL 的未来版本。

  2. 深入解码器本身以在运行时获取信息。您真正能找到的唯一半标准的东西是他们使用的是原始解码器还是位解码器,这根本没用(许多无损格式都需要位解码器),所以您最终可能会阅读所有 30进口商并编写十几段代码来从中提取信息。

  3. 将另一个库与(或代替)PIL 一起使用。例如,虽然 ImageMagick 绝对比 PIL 容易得多,但它确实有一个 API 可以告诉您图像文件使用哪种压缩类型。基本上,如果它是 UndefinedCompressionJPEGCompression 是有损的,其他任何东西都是无损的。主要的缺点(除了需要安装两个图像库)是PIL可以打开但IM不能打开的文件,反之亦然,以及PIL和IM处理不同的多图像文件,等等。

  4. 做你已经在做的事情。通读 30 个进口商,列出哪些是有损的,哪些是无损的。要处理有时无损的 JPEG 和 TIFF 等情况,您可能需要编写不会完全拒绝它们的代码,而是给出警告“这些文件可能有损。您确定要导入它们吗? " (或者,或者,只为所有有损格式提供“我知道我在做什么”覆盖,然后只考虑 JPEG 和 TIFF 有损。)

对于许多用例,我会非常谨慎地选择 #4,但对于您的用例,它实际上似乎很合理。您不是因为您的代码会崩溃,或者出于安全原因或类似原因而试图阻止有损图像;您只是想警告人们,如果他们提交 JPEG,他们将浪费大量时间获取无用的信息,对吗?

【讨论】:

  • 所有这些选项都不正确,对不起:/ 这些检查绝对不能保证。看到那边的那张png图片了吗?也许在它生命的早期它是一个 jpeg,也许在此之前它是来自某个传感器的一些原始数据。因此,试图以此区分输入是没有意义的。唯一明智的方法是在某处添加以下(调整后的)行:“亲爱的用户,收到的每个输入都将在进一步处理之前转换为格式 X。”
  • @mmgp:这就是为什么我说(在对问题的评论中,虽然不是答案)这实际上更多是消息传递和文档问题而不是编程问题。也许我应该重新构造答案来这么说。
猜你喜欢
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2012-04-13
  • 2012-10-05
  • 2022-12-16
  • 2017-09-28
相关资源
最近更新 更多