3

概述

我正在填充一个 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在这里没有提供有价值的解决方案。我不是在寻找任何奇迹,因为我知道大多数计算都需要很长的处理时间,我只需要在您可能需要提供的任何帮助和建议下尽可能减少这段时间。

4

2 回答 2

4

就个人而言,我会做几件事:

0) 在你分析你的代码以确保这实际上是减速发生的地方之前,不要做任何事情。

1)我不会使用 TImageList,而是使用 TList 后代来存储图像。我不确定这是否会对性能产生直接影响,但是 IIRC,TImageList 很大程度上依赖于内置的 Windows 图像处理,这可能会更慢。

2)如果可能的话,按需更新图像,而不是一起更新。

3)线程转换过程而不是在主线程中运行它。如果您还使用 TList,这非常简单,因为您只需将列表项传递给线程(或线程队列)。这具有使用多个处理器(如果可用)的额外好处。

线程最有可能提高应用程序的感知性能,即使它实际上可能不会花费更少的时间。将其与按需转换相结合,您应该会看到巨大的改进。

ETA:正如 Jerry 在评论中提到的那样,线程池是一个好主意。Embarcadero 网站上有一些这样的例子,如果你搜索他们的博客。

于 2012-05-29T23:56:42.387 回答
1

添加到蒂姆的优秀建议中:我不确定您如何访问您的位图,ScanLine如果您不这样做,请使用位图的属性。如果可能,请使用 pf32Bit,访问更容易,而且速度更快。

请注意位图不是线程安全的。读取扫描线是没有问题的,但是当你想写回结果时,一定要使用临界区或类似的东西。

强烈建议使用分析器,您会惊讶于哪些代码效率低下。我使用 ProDelphi:它不贵而且非常精确。

于 2012-05-30T05:40:22.787 回答