我需要在给定目录中显示图像的缩略图。在将图像加载到图像组件之前,我使用 TFileStream 读取图像文件。然后将位图调整为缩略图大小,并分配给 TScrollBox 上的 TImage 组件。
它似乎工作正常,但是对于较大的图像会减慢很多。
有没有更快的方法从磁盘加载(图像)文件并调整它们的大小?
谢谢,彼得
我需要在给定目录中显示图像的缩略图。在将图像加载到图像组件之前,我使用 TFileStream 读取图像文件。然后将位图调整为缩略图大小,并分配给 TScrollBox 上的 TImage 组件。
它似乎工作正常,但是对于较大的图像会减慢很多。
有没有更快的方法从磁盘加载(图像)文件并调整它们的大小?
谢谢,彼得
并不真地。您可以做的是在后台线程中调整它们的大小,并使用“占位符”图像,直到调整大小完成。然后,我会将这些调整大小的图像保存到某种缓存文件中以供以后处理(Windows 会这样做,并调用当前目录中的缓存 thumbs.db)。
线程架构本身有多种选择。处理所有图像的单个线程,或者一个线程只知道如何处理单个图像的线程池。AsyncCalls库甚至是另一种方式,可以让事情变得相当简单。
我将通过 skamradt 来补充答案,并尝试将其设计为尽可能快。为此,您应该
使用多线程意味着使用 VCL 类来调整大小是行不通的,因为 VCL 不是线程安全的,并且所有围绕它的 hack 都不能很好地扩展。efg 的计算机实验室有图像处理代码的链接。
使用多个线程时不要导致多个并发 I/O 操作很重要。如果您选择将缩略图图像写回文件,那么一旦您开始读取文件,您应该完全读取它,一旦您开始写入文件,您也应该完全写入它。交错这两个操作将杀死您的 I/O,因为您可能会导致硬盘磁头的大量查找操作。
为了获得最佳结果,文件的读取(和写入)也不应该发生在应用程序的主(GUI)线程中。这将建议以下设计:
编辑:
在重新阅读您的问题时,我注意到您可能只需要调整一个图像的大小,在这种情况下,单个背景线程当然就足够了。无论如何我都会留下我的答案,也许它会在某个时候对其他人有用。这是我从最近的一个项目中学到的,最终的程序可能需要更高的速度,但在高峰时间只使用了大约 75% 的四核机器。将 I/O 从处理中解耦会有所作为。
我经常将 TJPEGImage 与 Scale:=jsEighth 一起使用(在 Delphi 7 中)。这非常快,因为 JPEG 解压缩可以跳过大量数据来填充宽度和高度仅为八分之一的位图。
另一种选择是使用shell 的方法来提取缩略图,这也非常快
我从事视觉业务,我只是使用 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,因为它在时间上更加静态,并且更容易找到非游戏相关的示例。
利用 Windows 容量创建缩略图。还记得包含图像的文件夹中隐藏的 Thumbs.db 文件吗?
我已经实现了类似这个功能的东西,但是在 VB 中。我的软件能够在大约 10 秒内构建 100 个文件(混合大小)的缩略图。
我无法将其转换为 Delphi。
尝试查看Graphics32 库:它非常擅长绘制事物并且与位图配合得很好。它们是线程安全的,有很好的例子,而且完全免费。