いつもお世話になっています。GGです。
CImageクラスを使って、OnDraw()に描画しています。
imgOriginal.StretchBlt(pDC, xDest, yDest, xW, yH,
srcX, srcY, srcxWw, srcyH,
SRCCOPY);
どんどん拡大すると描画のスピードが遅くなりました。
どう解決したらいいでしょうか。
よろしくお願いします。
環境:.Net(2002) MFC使用、Win2000
遅くなること自体は多分、どうしようもない。
いいマシンに乗り換えるとか、オンボード以外のグラボを入れてみるとか?
軽減策という意味だと「ダブルバッファ」とか「裏画面」とか調べてみると
改善はできるかもしれません。
StrechBltはデバイスドライバの実装に依存していたと思いますけれど、
基本的にそんなに高速な物ではなかったと思います。
基本的にGDIで提供されているインターフェイスは汎用性が高い分低速です。
高速な画像処理ライブラリとかを使わないと多分大幅な改善は無理でしょう。
この辺は色々調べて見たほうが良いと思いますけれど、本当に高速な奴は
きっと有償で結構高いのではと思いますね。
そのくらいの価値はあると思うので。
メモリDCで拡大してからBitBltで転送でどの程度改善されるかは
わかりませんけれど、多分大幅な改善は望めないと思います。
srcX, srcY, srcxWw, srcyH を変化させずに拡大してるのでしょうか?
見えない部分を描画するのは無駄なので、クリッピングすれば1ピクセルで画面が埋まる
寸前で、上下左右(斜めにも)1画面分(未満)の9画面分(弱)の描画が最大負荷になりま
す。
> srcX, srcY, srcxWw, srcyH を変化させずに拡大してるのでしょうか?
> 見えない部分を描画するのは無駄なので、クリッピングすれば1ピクセルで画面が埋まる
> 寸前で、上下左右(斜めにも)1画面分(未満)の9画面分(弱)の描画が最大負荷になります。
確かにそうですね。
試してみる価値がありそう。
かなり無駄な処理をしている可能性が高そうです。
まあ、どの程度まで拡大した時の事を言っているのかとか、
どの程度のスピードを遅いといっているのか等の客観的な指標が無いので
言われている状況が正確にはつかめませんけれど。
Banさん、PATIOさん、ISLeさん、PATIOさん
ご回答ありがとう。
>srcX, srcY, srcxWw, srcyH を変化させずに拡大してるのでしょうか?
そうです。
>見えない部分を描画するのは無駄なので、クリッピングすれば1ピクセルで画面が埋まる
>寸前で、上下左右(斜めにも)1画面分(未満)の9画面分(弱)の描画が最大負荷になりま
>す。
そうと思っています。
確かに、無駄の部分がカットすれば、かなり早くなります。
でも、クリッピングするの方法がわかりません。
>まあ、どの程度まで拡大した時の事を言っているのかとか、
>どの程度のスピードを遅いといっているのか等の客観的な指標が無いので
>言われている状況が正確にはつかめませんけれど。
目で確認していますが、拡大すると画面が真っ白の時間があります、
拡大によって、その時間が長くなります(約1秒ぐらい)。
頻繁に拡大縮小すと、気分が悪くなります。
よろしくお願いします。
>クリッピングするの方法
とりあえず、拡大後に表示されるソース側の四角形の位置と大きさを計算し
て、それより若干広い範囲をソース側に指定して、描画先の大きさは実際に描
画したい面積より若干広い範囲を指定するって方法を提案します。
効果が出るかどうかは多分デバイス依存ですけどね。
若干としているのは、拡大率と併せてアレコレ考えて計算する必要があるからで
す。
拡大後の位置の正確さにこだわりが無いならどうでも良い部分です。
詳しくは、ソース側は描画範囲に一部でも重なるピクセル+1を範囲として指定し
て、出力側はソース側の必要ない部分を拡大率分拡大した範囲を指定して描
画時に切り捨てさせる事になります。
ソース側の+1を行わず拡大範囲丁度にすると、画面端の補完が多分変わりま
す。
本当のクリッピングはデバイスコンテキストに有ります。
色々設定方法が有るので、MSDN引いたほうが早いです。
GetClipBox(GetBoundsRect)で現在の領域を取得、
ExcludeClipRectでそれを除外、
IntersectClipRect(SetBoundsRect)あたりで必要な大きさを指定、
描画、
必要ならまた除外してから元の領域を再設定、
でしょうか。自信ないです。
あと、速度に関して、SetStretchBltModeでHALFTONEをCOLORONCOLOR
に変更すると早くなったりするかも知れません。
…普通は標準でCOLORONCOLORだったっけ?
注意事項:この機能はデバイス依存なので使えない場合があるそうです。
処理速度もデバイス依存。
>>MSDN//StretchBlt
>すべてのデバイスが StretchBlt 関数をサポートするわけではありません。
>詳しくは GetDeviceCaps 関数の説明を参照してください。
ここで言っているクリッピングと言うのは、
多分、話の筋から言ってぬさんが提示している最初の方の方法でしょう。
これによって大幅に処理負荷が抑えられるはず。
で、拡大率等でsrc側の基準点やサイズを計算するのは
自分で考えましょう。そんなに難しい計算ではないはずですし。
ただ、この方法をとると画像のスクロール時にも再描画を
かけないといけないのでその辺はちゃんと考慮に入れる必要がありそうですね。
ぬさん、PATIOさん
ご回答ありがとう。
ぬさん書いたクリッピングの方法は簡単にできるわけではないですが、
参考しながら、やってみます。
>自分で考えましょう。そんなに難しい計算ではないはずですし。
そうですね、わかれば、そんなに難しい計算ではないかもしれません。
どうも、ありがとうございました。