【问题标题】:What is the fastest way of loading and re-sizing an image?加载和调整图像大小的最快方法是什么?
【发布时间】:2010-10-24 13:18:19
【问题描述】:

我需要在给定目录中显示图像的缩略图。在将图像加载到图像组件之前,我使用 TFileStream 读取图像文件。然后将位图调整为缩略图大小,并分配给 TScrollBox 上的 TImage 组件。

它似乎工作正常,但是对于较大的图像会减慢很多。

有没有更快的方法从磁盘加载(图像)文件并调整它们的大小?

谢谢,彼得

【问题讨论】:

    标签: delphi image thumbnails filestream


    【解决方案1】:

    不是真的。您可以做的是在后台线程中调整它们的大小,并使用“占位符”图像直到调整大小完成。然后我会将这些调整大小的图像保存到某种缓存文件中以供以后处理(Windows 会这样做,并调用当前目录中的缓存 thumbs.db)。

    线程架构本身有多种选择。处理所有图像的单个线程,或者一个线程只知道如何处理单个图像的线程池。 AsyncCalls 库甚至是另一种方式,可以让事情变得相当简单。

    【讨论】:

    • 我的应用程序现在使用占位符和线程(skamradt、mghie)并且它运行良好。按照 Stijn Sanders 的建议提取缩略图。谢谢你。彼得。
    • 不幸的是,AsyncCalls 已死(已停产)。
    【解决方案2】:

    我将补充 skamradt 的答案,并尝试将其设计为尽可能快。为此,您应该

    • 优化 I/O
    • 使用多个线程来利用多个 CPU 内核,并在您读取(或写入)文件时保持单个 CPU 内核工作

    使用多线程意味着使用 VCL 类来调整大小是行不通的,因为 VCL 不是线程安全的,并且所有围绕它的 hack 都不能很好地扩展。 efg's Computer Lab 有图片处理代码的链接。

    在使用多个线程时不要导致多个并发 I/O 操作,这一点很重要。如果您选择将缩略图图像写回文件,那么一旦您开始读取文件,您应该完全读取它,一旦您开始写入文件,您也应该完全写入它。交错这两个操作会杀死您的 I/O,因为您可能会导致硬盘磁头的大量查找操作。

    为获得最佳结果,文件的读取(和写入)也不应发生在应用程序的主 (GUI) 线程中。这将建议以下设计:

    • 让一个线程将文件读入 TGraphic 对象,并将它们放入线程安全列表中。
    • 让线程池等待原始大小的文件列表,并让一个线程处理一个 TGraphic 对象,将其调整为另一个 TGraphic 对象,然后将其添加到另一个线程安全列表中。
    • 通知 GUI 线程添加到列表中的每个缩略图,以便显示。
    • 如果要将缩略图写入文件,也请在阅读线程中执行此操作(请参阅上面的说明)。

    编辑:

    在重新阅读您的问题时,我注意到您可能只需要调整一张图片的大小,在这种情况下,单个后台线程当然就足够了。无论如何我都会留下我的答案,也许它会在某个时候对其他人有用。这是我从最近的一个项目中学到的,最终的程序可能需要更高的速度,但在高峰时间只使用了大约 75% 的四核机器。将 I/O 与处理分离会有所作为。

    【讨论】:

      【解决方案3】:

      我经常使用带有 Scale:=jsEighth 的 TJPEGImage(在 Delphi 7 中)。这非常快,因为 JPEG 解压缩可以跳过大量数据以填充宽度和高度仅为八分之一的位图。

      另一种选择是使用shell's method to extract a thumbnail,它也非常快

      【讨论】:

      • 这看起来不错。去年我很想弄清楚这一点,但现在我不再关心太多了。但是我仍然可以使用 TJPEGImage.Scale 方法修复我的一些应用程序。谢谢
      【解决方案4】:

      我从事视觉业务,我只是使用 OpenGL 将图像上传到 GPU。 (通常每秒 20x 2048x2000x8bpp),每个纹理一个 bmp,并让视频卡缩放(win32,Mike Lischke 的 opengl 标头)

      上传此类图像需要 5-10 毫秒,具体取决于具体的显卡(如果未集成和 nvidia 7300 系列或更高版本。最近的集成 GPU 也可能是可行的)。缩放和显示成本 300us。这意味着客户可以在不接触应用程序的情况下疯狂地平移和缩放。我在它上面画了一个叠加层(它曾经是一个 tmetafile,但现在是一种自己的格式)。

      我最大的图片是 4096x7000x8bpp,它在 30 毫秒内显示和缩放。 (GF 8600)

      这项技术的一个限制是最大纹理大小。它可以通过将图片分割成多个纹理来解决,但我还没有打扰,因为我通过软件交付系统。

      (一些典型尺寸: nv6x00 系列:2k*2k,但与 GDI 相比,上传几乎是收支平衡 nv7x00 系列:4k*4k 对我来说是基准卡。 GF7300 的价格是 20-40 美元 nv8x00系列:8k*8k )

      请注意,这可能并不适合所有人。但是,如果您有幸指定硬件限制,它可能会起作用。主要问题是像 Thinkpad 这样的笔记本电脑,其 GPU 比普通笔记本电脑更老,而后者通常比台式机落后一代。

      我选择了 OpenGL 而不是 DirectX,因为它在时间上更加静态,并且更容易找到与游戏无关的示例。

      【讨论】:

        【解决方案5】:

        利用窗口容量来创建缩略图。还记得包含图像的文件夹中隐藏的 Thumbs.db 文件吗?

        我已经在 VB 中实现了类似此功能的功能。我的软件能够在大约 10 秒内构建 100 个文件(混合大小)的缩略图。

        但我无法将其转换为 Delphi。

        【讨论】:

          【解决方案6】:

          试试看Graphics32 library:它非常擅长绘制东西,并且与位图配合使用很棒。它们是线程安全的,有很好的例子,而且完全免费。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-25
            • 1970-01-01
            • 2011-01-07
            • 2016-05-30
            • 2011-07-09
            • 2012-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多