【发布时间】:2012-05-29 23:45:15
【问题描述】:
概述
我正在填充一个 ViewStyle 设置为 vsIcon 的 TListView。 Listview 连接到 TImageList,其中添加到 Listview 的每个项目都有自己的图像,由相应的索引指定。
我们的想法是能够一次性自动处理一系列位图。每个位图都不同,但大小始终相同。
由于其工作原理,对于添加到 ImageList 的位图数量从来没有固定的大小或限制,唯一的限制是可用的系统内存。
问题
我遇到的问题与对这些位图的操作性能有关。我所说的操作是指对位图执行不同的图像处理技术,例如灰度、交换颜色、调整亮度等。
现在假设调整大小为 1Mb 的位图的亮度需要 3 秒。如果 ImageList 总共有 10 个位图,那么这个过程现在大约需要 30 秒。
(注意:我没有用 GetTickCount 或任何东西测试过速度,这些只是示例)。
请考虑这样一个事实,尽管正如我之前所说,这个 ImageList 可以是任何大小,但处理时间可能会持续很长时间。
当我对这些位图执行任何操作时,我在循环中使用 GetBitmap 将每个位图发送到屏幕外缓冲区位图以执行操作,如下所示:
var
Bmp: TBitmap;
i: Integer;
begin
Bmp := TBitmap.Create;
try
ImageList1.BeginUpdate;
try
for i := 0 to ImageList1.Count - 1 do
begin
ImageList1.GetBitmap(i, Bmp);
Bmp.PixelFormat := pf24Bit;
// perform manipulation to Bmp here
ImageList1.Replace(i, Bmp, nil);
end;
finally
ImageList1.EndUpdate;
end;
finally
Bmp.Free;
end;
end;
在可能包含任意大小或数量的图像的 ImageList 上运行它,您可能会理解这可能会很慢。
我正在寻找优化和改进执行此操作的方法的方法,因为目前它在性能方面还远未达到可接受的水平。 BeginUpdate 和 EndUpdate 在这里没有提供有价值的解决方案。我不是在寻找任何奇迹,因为我知道大多数计算都需要很长的处理时间,我只需要在您可能需要提供的任何帮助和建议下尽可能减少这段时间。
【问题讨论】:
-
我不得不说多线程是你需要走的路,但不仅仅是任何一个,你需要一个线程池。 OmniThreadLibrary 有很好的资源,请看这里:otl.17slon.com 不要像我曾经尝试过的那样尝试同时创建 700 多个线程(假设有 700 个图像) - 因为这实际上会杀死您的计算机。线程池的想法是一次运行 5 个线程,而其余的则留在队列中等待。一旦一个线程完成,就会触发另一个线程,因此一次运行的线程可能不会超过 5 个。
-
@JerryDodge by threads 你的意思是利用 cpu 上的每个可用内核吗?
-
不,他的意思是使用
TThreads。这些将同时运行,允许您同时处理多个图像,而您的应用程序 UI 将保持响应。从理论上讲,如果可用,操作系统会将线程分配给备用内核,您不必担心。 -
@TimSullivan 感谢您的澄清
-
我会说将线程限制设置为 20-30,在一台好机器上可能是 50,但是当同时处理数百个位图时,您需要考虑计算机的性能。也许计算可用内存与您打算处理的每个图像的大小,并根据可用内存创建线程数。