2009-05-28 27 views
11

私はSystem.Drawingクラスを使用して、ユーザーがアップロードした写真からサムネイルと透かし入り画像を生成しています。ユーザーは、オリジナルをアップロードした後、jCropを使用して画像をトリミングすることもできます。私はこのコードを他の誰かから引き継いでおり、単純化して最適化しようとしています(トラフィックの多いWebサイトで使用されています)。C#での効率的な画像操作

以前の人は、パラメータとしてビットマップを受け取った静的メソッドを持っていて、Graphicsオブジェクトを内部的に割り当て、廃棄しました。私の理解では、インスタンスは画像全体をメモリに格納していますが、Graphicsは基本的に描画操作のキューであり、それは冪等元です。次のように

プロセスは、現在動作します:

  • は、画像を受信し、一時ファイルに保存します。
  • 作物座標を受け取ります。
  • 元のビットマップをメモリにロードします。
  • オリジナルから新しいビットマップを作成し、クロッピングを適用します。
  • 多分、新しいビットマップ上で調整するいくつかのクレイジー・お尻の明るさを行い、新たなビットマップを返します(私はむしろ、この手を触れないと思います!;ポインタ算術演算はたくさんある)(?)から、別のビットマップを作成します
  • このA.を呼び出すことができます透かし(このB1を呼び出すことができます)
  • を適用した一つは、A.
  • から175x175サムネイルビットマップを作成します。これは、メモリの割り当ての多くのように思えるA.

から45x45のサムネイルビットマップを作成します。私の質問はこれです:実際にパイプラインを作成して、コードの一部を書き換えてGraphicsインスタンスを再利用することをお勧めしますか?実際には、メモリに1つのイメージ(オリジナルのアップロード)しか必要としませんが、残りはディスクに直接書き込むことができます。生成されたすべてのイメージには、クロップおよび輝度の変換、およびそのバージョンに固有の単一の変換が必要となり、効果的に操作のツリーが作成されます。

ご意見やご提案はありますか?

ああ、私は実際に.NETで実際に作業していることに言及する必要があります。私が言うことが混乱していると思われる場合は、私に負担をかけてヒントを教えてください。

+0

これは、.NETとの最初のやりとりであることは残念です。 IDisposableパターンは、フレームワークに関する私の本当の唯一の永続的な不満です。この '使用する'ビジネスは、最も難解な、定期的に使用される機能です。ほとんどのものは非常に簡単です。 – overslacked

+0

良い質問、私は言う! +1 – Cerebrus

+1

私は「冪等級」を見なければなりません...良い言葉。 – JasonRShaver

答えて

3

再利用Graphicsオブジェクトは、おそらく重要なパフォーマンスの向上にはなりません。

基本的なGDIコードは、RAM(メモリDC)にロードしたビットマップのデバイスコンテキストを簡単に作成します。

操作のボトルネックは、ディスクから画像を読み込むことにあるようです。

ディスクからイメージをリロードするのはなぜですか?すでにアップロードされているはずのRAMのバイト配列にある場合は、バイト配列にメモリストリームを作成し、そのメモリストリームからビットマップを作成するだけです。

つまり、ディスクに保存しますが、リロードしないでください。RAMから操作するだけです。

また、あなたは(それが行わたい方法に応じて。)透かしを適用するために、新しいビットマップを作成する必要はありません

あなたはそれが改善を必要とする場所を確認するための操作をプロファイル(あるいはそれならばなければなりません)改善する必要があります。

3

このプロセスは妥当と思われます。各イメージはディスクに保存される前にメモリに存在しなければならないので、サムネイルの各バージョンが最初にメモリに格納されます。これが効率的に機能することを確認するための鍵は、グラフィックスとビットマップオブジェクトを廃棄することです。これを行う最も簡単な方法はusingステートメントです。

using(Bitmap b = new Bitmap(175, 175)) 
using(Graphics g = Graphics.FromBitmap(b)) 
{ 
    ... 
} 
+0

本当の質問はもっと似ています:私が 'Graphics'オブジェクトを再利用すればパフォーマンスが向上しますか? –

0

私は何気なく存在し、これを捨てるしようとしていますが、画像を操作するためのベストプラクティスへの迅速な「ガイド」を望んでいた場合は、Paint.NETのプロジェクトを見ています。画像処理を行うための無料の高性能ツールについては、AForge.NETをご覧ください。

AForgeの利点は、毎回新しいビットマップを作成せずにこれらの手順を大量に実行できるようにすることです。これがウェブサイトの場合は、作業しているコードがアプリケーションのパフォーマンスのボトルネックになることはほとんど認められます。

2

もう少し似たようなプロジェクトを完成させ、すべての画像に対して新しいものをスピンアップするのではなく、グラフィックスオブジェクトを再利用すればパフォーマンスに違いがあるかどうかを確認するための実用的なテストを行いました。私の場合、私は大量のイメージ( "バッチ"で10,000以上)の安定したストリームに取り組んでいました。私は、Graphicsオブジェクトを再利用することでパフォーマンスが少し向上したことがわかりました。

GraphicsオブジェクトのGraphicsContainersを使用して、多少の増加を得ました。さまざまな動作を実行するために使用されたように、さまざまな状態をオブジェクトに簡単に入れ替えることができます。 (具体的には、作物を適用して各画像にテキストとボックス(四角形)を描画しなければなりませんでした。)これがあなたがしなければならないことに意味があるかどうかは分かりません。 GraphicsオブジェクトのBeginContainerメソッドとEndContainerメソッドを見たいと思うかもしれません。

私の場合、その差はわずかでした。あなたの実装が多かれ少なかれ向上するかどうかは分かりません。しかし、コードを書き直すコストがかかりますので、書き直す前に現在のデザインを終了し、いくつかのperfテストを行うことを検討してください。ちょっとした考え。

あなたが役立つかもしれないいくつかのリンク:

Using Nested Graphics Containers
GraphicsContainer Class

関連する問題