【问题标题】:How to check if file is/isn't an image without loading full file? Is there an image header-reading library?如何在不加载完整文件的情况下检查文件是否是/不是图像?是否有图像标题阅读库?
【发布时间】:2009-12-30 17:15:48
【问题描述】:

编辑:

抱歉,我想我的问题含糊不清。我想有一种方法来检查文件是否不是图像,而不会浪费时间加载整个图像,因为这样我可以稍后再进行其余的加载。我不想只检查文件扩展名。

应用程序只查看图像。通过“检查有效性”,我的意思是也在目录中“检测并跳过非图像文件”。如果像素数据已损坏,我仍想将其视为图像。

我分配页码并将这些图像配对。有些图像是单个左页或右页。有些图像很宽,是左右页面的“展开”。例如, pagesAt(3) 和 pagesAt(4) 可以返回相同的 std::pair 图像或 std::pair 相同的宽图像。

有时,有奇数个“薄”图像,第一个图像将单独显示,类似于宽图像。一个示例是单个封面。

不知道目录中的哪些文件是非图像意味着我无法自信地分配这些页码并将文件配对以进行显示。此外,用户可能决定跳转到第 X 页,当我后来发现并删除非图像文件并相应地重新分配页码时,第 X 页可能看起来是不同的图像。

原创

如果重要的话,我使用的是 Qt 库中的 c++ 和 QImage。

我正在遍历一个目录并在图像路径上使用 QImage 构造函数。当然,这非常慢,并且会使应用程序感觉没有响应。但是,它确实允许我检测无效的图像文件并尽早忽略它们。

我可以在浏览目录时仅保存图像的路径,并仅在需要时才实际加载它们,但是我不知道图像是否无效。

我正在考虑将这两者结合起来。即在遍历目录时,仅读取图像的标题以检查有效性,然后在需要时加载图像数据。

所以,

只加载图片标题会比加载整个图片快得多吗?还是做一些 i/o 来读取标题意味着我还不如完全加载图像?稍后,我还将解压缩存档中的图像,因此这也适用于仅解压缩标题与解压缩整个文件。

另外,我不知道如何加载/读取只是图像标题。是否有一个可以只读取图像标题的库?否则,我必须自己打开所有文件类型的流和代码图像标题阅读器的每个文件。

【问题讨论】:

  • 您需要多快才能知道图像是否有效? (立即,在拨打电话后立即,或在某个未定义的时间后?)您对图像做了什么 - 操作它,显示它,或者只是将数据移动到其他地方?
  • 我在上面澄清了我的问题。通过有效性,我的意思是检测非图像文件,而不仅仅是查看文件扩展名或加载完整的图像文件。这就是为什么我问是否有办法仅在遍历目录时检查标题。

标签: c++ image qt file-io qimage


【解决方案1】:

Unix file 工具(几乎永远存在)正是这样做的。这是一个简单的工具,它使用已知文件头和二进制签名的数据库来识别文件的类型(并可能提取一些简单的信息)。

数据库是一个简单的文本文件(为了提高效率而编译),它使用简单的结构化格式(记录在man magic)描述了大量的二进制文件格式。源代码在/usr/share/file/magic(在 Ubuntu 中)。例如,PNG 文件格式的条目如下所示:

0       string          \x89PNG\x0d\x0a\x1a\x0a         PNG image
!:mime  image/png
>16     belong          x               \b, %ld x
>20     belong          x               %ld,
>24     byte            x               %d-bit
>25     byte            0               grayscale,
>25     byte            2               \b/color RGB,
>25     byte            3               colormap,
>25     byte            4               gray+alpha,
>25     byte            6               \b/color RGBA,
>28     byte            0               non-interlaced
>28     byte            1               interlaced

您可以仅提取图像文件类型的签名,并构建您自己的“嗅探器”,甚至可以使用来自 file 工具(似乎是 BSD 许可)的解析器。

【讨论】:

  • 很好,谢谢。但我想让这个应用程序跨平台工作,所以我不能依赖 unix 系统调用。 “构建我自己的“嗅探器””是指编写我自己的“标题阅读器”吗?或者你是说我有办法获得那个file 工具的源代码?
  • 没关系,我找到了它的来源。现在我只需要看看我是否可以直接使用它,或者我是否必须用它编写自己的代码。
【解决方案2】:

只是为了增加我的 2 美分:您可以使用 QImageReader 获取有关图像文件的信息而无需实际加载文件。

例如使用 .format 方法,您可以检查文件的图像格式。

来自官方 Qt 文档 (http://qt-project.org/doc/qt-4.8/qimagereader.html#format):

返回 QImageReader 用于读取图像的格式。你可以打电话 在将设备分配给阅读器以确定该功能后,此功能 设备的格式。例如:QImageReader reader("image.png"); // reader.format() == "png" 如果阅读器无法读取任何图片 设备(例如,那里没有图像,或者图像已经 已读取),或者如果格式不受支持,则此函数返回 空 QByteArray()。

【讨论】:

    【解决方案3】:

    我不知道仅加载标题的答案,这可能取决于您尝试加载的图像类型。如果可能的话,您可以考虑使用 Qt::Concurrent 浏览图像,同时允许程序的其余部分继续执行。在这种情况下,您最初可能会将所有条目表示为未知状态,然后在验证完成后更改为 image 或 not-an-image。

    【讨论】:

    • 很可能所有图像的格式都相同——可能只有一两个不同。一旦我找到两/三张相同格式的图像,我就有足够的信心假设其余的图像也都是一样的。
    【解决方案4】:

    如果您谈论的是一般的图像文件,而不仅仅是特定的格式,我敢打赌,在某些情况下图像标题是有效的,但图像数据不是。你还没有对你的应用程序说什么,你有没有办法在后台添加一个线程,可能会在内存中保留一些图像,并根据用户接下来可能加载的内容来交换它们? IE:幻灯片应用程序会在当前图像前后加载 1 或 2 张图像。或者可能在图像名称旁边显示一个问号,直到后台线程可以验证数据的有效性。

    【讨论】:

    • 损坏的数据是可以的。之前不是很清楚,不好意思。我真正需要的是以一种比查看文件扩展名或浪费时间加载完整图像更智能的方式检测非图像。
    【解决方案5】:

    虽然在本地文件系统上打开和读取文件的标头不应该太昂贵,但如果文件位于远程(网络)文件系统上,它可能会很昂贵。更糟糕的是,如果您正在访问使用hierarchical storage management 保存的文件,读取文件可能会非常昂贵。

    如果这个应用程序只适合您,那么您可以决定不担心这些问题。但是,如果您要向公众发布您的应用程序,那么在绝对必要之前阅读文件会给某些用户带来问题。

    Raymond Chen 为他的博客The Old New Thing 写了一篇关于此的文章。

    【讨论】:

    • 我认为这不会是个问题。这是一个 gui 应用程序,最终用户可以像阅读书中的页面一样阅读图像,所以它都是本地的。在最坏的情况下,我认为它只是在外部硬盘驱动器或附近的 LAN 上。
    猜你喜欢
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 2018-03-29
    • 2011-01-12
    • 1970-01-01
    相关资源
    最近更新 更多