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: ジェリーがコメントで述べたように、スレッド プールは良い考えです。ブログを検索すると、Embarcadero のサイトにこの例がいくつかあります。

于 2012-05-29T23:56:42.387 に答える
1

ティムの優れた提案に追加:ビットマップにアクセスする方法がわかりません。アクセスScanLineしなかった場合は、ビットマップのプロパティを使用してください。また、可能であればpf32Bitを使用すると、アクセスがより簡単になり、ほとんどの場合さらに高速になります。

ビットマップはスレッドセーフではないことに注意してください。スキャンラインを読み取ることは問題ありませんが、結果を書き戻す場合は、必ずクリティカルセクションなどを使用してください。

プロファイラーを使用することを強くお勧めします。どのコードが非効率的であるかどうかに驚かれることでしょう。私はProDelphiを使用しています。高価ではなく、非常に正確です。

于 2012-05-30T05:40:22.787 に答える