2009-08-31 5 views
15

ユーザーのアップロードしたイメージのサイズを変更するためのWebサービスを作成しましたが、機能上は正常に動作しますが、使用するたびにCPU使用率が急上昇します。 Windows Server 2008 64ビット版で動作しています。私は32と64ビットにコンパイルしようとしており、ほぼ同じ結果を得ています。C#と.NET 3.5のイメージのサイズ変更の効率

サービスの心は、この機能である:私はサービス上でプロファイラを入れて、それが時間の大半はGDI +ライブラリ自体に費やされている指示するように見えたし、あまりありません

private Image CreateReducedImage(Image imgOrig, Size NewSize) 
{ 
    var newBM = new Bitmap(NewSize.Width, NewSize.Height); 
    using (var newGrapics = Graphics.FromImage(newBM)) 
    { 
     newGrapics.CompositingQuality = CompositingQuality.HighSpeed; 
     newGrapics.SmoothingMode = SmoothingMode.HighSpeed; 
     newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
     newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, NewSize.Width, NewSize.Height)); 
    } 

    return newBM; 
} 

私のコードで得ることができます。

質問: ここで私のコードでは驚くほど非効率的なことをしていますか?私が見た例に従っているようです。

GDI +以外のライブラリを使用することで得られる利益はありますか?私が見てきたベンチマークは、GDI +が他のライブラリとよく似ていることを示しているようですが、十分に自信を持って見つけられませんでした。

「安全でないコード」ブロックを使用することで得られる利益はありますか?

私がコードを十分に含んでいないかどうか教えてください...私は要望どおりに置くことができますが、投稿に不快感を与えたくはありません。

+0

タイトなループでこれを実行すると、入力/出力イメージのサイズで処理できるイメージの数はいくつですか? –

+0

コードの一部の画像サイズ変更をローカルで実行すると、45秒間に1000画像のサイズを変更できます。 873x655を入力し、300x250にサイズ変更してトリミングします。 –

+0

何か間違っています。 [ASP.NET用のImageResizerライブラリ](http://imageresizing.net)はGDI +を内部的に使用し、スループットが大幅に向上しています。 I/Oが処理される方法が原因であると思われます.Image/Bitmapインスタンスを作成する前にファイルストリームをメモリにバッファリングすると、並行性の欠陥がなくなります。 –

答えて

6

通常、画像処理は高価な処理です。 32ビットのカラーイメージは、アプリケーションが何らかの処理を開始する前に、メモリ内で4ピクセル幅*ピクセルの高さに拡張されていることを覚えておく必要があります。あらゆる種類のピクセル処理を行う場合、特にスパイクが予想されます。

言われていることは、プロセスのスピードアップやプロセッサへの影響を軽減できることを私が見ている唯一の場所は、低品質の補間モードを試すことです。

3

Windows 7でリリースされたDirectXは、2Dハードウェアアクセラレーションを提供すると言われています。これがこの種の操作でGDI +を打ち負かすことを意味するかどうかは分かりませんが、 MSにはGDI hereの説明があり、それはとりわけ遅くなることを意味します。

この種のものを自分で実際にやりたければ、それを示す素晴らしいGDI Tutorialがあります。著者はチュートリアルのさまざまな部分でSetPixelと「安全でないブロック」の両方を使用しています。

サーバーに複数のCPUが搭載されていると仮定すると、マルチスレッド化が役に立ちます。つまり、一度に複数の画像を処理し、おそらくより高速な結果を得ることができます。

2

あなたは、ほとんどのプロセッサ集約型のリサンプリング操作のだろうが、もちろんあなたがして、画像品質を失うことになるHighQualityBicubicとして

newGrapics.InterpolationMode = InterpolationMode.Low; 

を試みることができます。

それ以外にも、コードをスピードアップするためにできることはありません。 GDI +は、Windowsマシン上では最も確かに高速です(C#で書かれたコードは純粋なCライブラリを上回ることはありません)。また、他の画像ライブラリを使用すると、unsafeやバグコードの潜在的なリスクが発生します。

画像のサイズを変更することは、あなたが何をしていても高価な操作です。最も簡単な解決策は、サーバーのCPUをより高速なモデルに置き換えることです。

0

私は補間モードを右に上げているので、スパイクがあると思われます。すべての補間モードはピクセル単位で動作し、BiCubicの高品質はGDI +と同じくらい高いので、ピクセル単位の計算がCPUを噛んでいると思われます。
テストとして補間モードをInterpolationModeNearestNeighborに落として、CPUスパイクが低下しているかどうかを確認してください。もしそうなら、それがあなたの犯人です。
ので、その後、品質対コストのためのいくつかの試行錯誤を行い、チャンスはあなたがまともな結果に

2

を取得するために、高品質双三を必要としない場合がありますされている場合は、

を書くとき、私は のサイズを変更するには、Webサービスを書かれていますユーザーがアップロードした画像

ユーザーが(Web?)サーバーに画像をアップロードした後、サーバーはスケーリングを行うためにWebサービスを呼び出しますか?

この場合、スケーリングをサーバーに直接移動するだけです。 Imhoは、画像を拡大しても、それが自分のWebサービスであるとは正当化しません。また、サーバーからWebサービスへの不要なトラフィックはかなり少なくなります。特に、画像がおそらくbase64でエンコードされているため、データトラフィックがさらに大きくなります。

しかし、私はここで推測しています。

p.s.安全でないブロック自体は何の利得も与えず、安全でないコードをコンパイルすることを許可します。したがって、独自のスケーリングルーティングを記述しない限り、安全でないブロックは役に立たないでしょう。

2

ImageMagickを試してみるとよいでしょう。無料で、.NETラッパー(click here)もあります。またはhere。 または、DOSシェルにコマンドを送信できます。

Windows Server上でImageMagickを使用した後、バッチ処理や時にはより柔軟なイメージ変換を行うためにImageMagickを使用しました。

もちろん、LeadtoolsとAtalasoftの製品のような市販のコンポーネントもあります。私たちはそれらを試したことはありません。

関連する問題