
GDI+を利用してお絵かきツールのようなものを作成しようと思っています。
しかしdrawImage()での画面への描画が非常に遅いようで、描いてみると線がカクカクしてしまいます。
アンチエイリアスやアルファブレンドが必要なのでGDI+を利用したいのですが、どうにか高速に描画させる方法はないでしょうか?
下記は現在のソースの一部です。
static Bitmap *offscreenBitmap//描画処理はこっちに
static Graphics *offscreen;
static Graphics *onscreen;//画面表示用
static RECT rect;//クライアント領域
static POINTS posPts,pts; //一つ前と現在のマウス座標
static BOOL bLButtonDown;
Pen nomalPen(Color(100,0,0,0), 1); //描画用ペン
switch(msg){
case WM_CREATE:
GetClientRect(hWnd,&rect);
offscreenBitmap = new Bitmap(rect.right, rect.bottom);//ビットマップ生成
offscreen = new Graphics(offscreenBitmap);
offscreen->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
offscreen->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);//アンチエイリアス有効化
offscreen->Clear(Color(255,255,255));//初期化
onscreen = new Graphics(hWnd);//ウインドウ表示用
onscreen->SetCompositingMode(CompositingModeSourceCopy);
break;
case WM_LBTTONDOWN:
bLButtonDown = TRUE;
posPts=MAKEPOINTS(lp)
break;
case WM_MOVE:
pts=MAKEPOINTS(lp)
if(bLButtonDown){
offscreen->DrawLine(&nomalPen, posPts.x, posPts.y, pts.x, pts.y);//線描画
posPts.x=pts.x;
posPts.y=pts.y;
}
InvalidateRect(hWnd,&rect,0);//ウインドウを更新
break;
case WM_PAINT:
onscreen->DrawImage(offscreenBitmap,0,0);//画面に書き出し
break;
}
No.3ベストアンサー
- 回答日時:
昔の絵描きツールでは一般に
1.MouseがDown->Move->UpまではキャッシュDC(GetDC())に書き出す。
2.この間描画データ(=1ストローク=座標の配列)は別途保管
3.Mouse Upで、裏DCに1ストロークを描画しなおし。
4.アンドInvalidateRectする(もちろんストロークデータを
含む矩形のみを無効化)。
5.WM_PAINTで「裏->表」転送を実行
てな感じです。最近はPCが早いのでこうなってない場合も多いです。
どこか参考になるところがあれば幸いです。
回答ありがとうございます。
getDC()で得られるDCってことはこの場合Onscreenってことですかね。ちらつきを抑止したいのでこれは試していませんが、無効化の領域を絞ることである程度速度が改善しました。
No.2
- 回答日時:
こんばんは。
offscreen->DrawLine(&nomalPen, posPts.x, posPts.y, pts.x, pts.y);
の代わりに
onscreen->DrawLine(&nomalPen, posPts.x, posPts.y, pts.x, pts.y);
へ直描きした場合が一番高速でした。
バックバッファ(オフスクリーン)への書き込みが相当に重たいようです。
初めてマウスを押したポイントと、離されたポイントの矩形領域を、バックバッファにストアした方が効果的かもしれません(アンドゥ・リドゥ程度ならば此れ出来そう)。
但し、リアルタイムにエフェクターを掛けながら描写をする場合は、どうしても作業用のバックバッファが必要になりそうです。
一応CachedBitmapと言うのが速いらしいのですが、
「参考資料」
http://lamoo.s53.xrea.com/develop/gdiplus/gdiplu …
http://lamoo.s53.xrea.com/develop/gdiplus/gdiplu …
画面に書き出す際に
onscreen->DrawImage(offscreenBitmap,0,0);
とする代わりに、こんな感じで呼び出す
CachedBitmap offcache(offscreenBitmap, onscreen);
onscreen->DrawCachedBitmap(&offcache, 0, 0);
らしいのですが、反ってスピードが落ちました・・・。
後、new Bitmap()の第3パラメータに「PixelFormat32bppRGB」とかを指定しても駄目でしょうか(少~しだけ速くなった気がした)。
回答ありがとうございます。
元々GDIで作っていたのですがアンチエイリアスや回転処理が欲しくなったのでGDI+に切り替えようとしてのっけから躓いてました。
URLの速度比較を見る限りGDI+は圧倒的に遅いみたいですね…
GDI+のメソッド云々よりもGdiplus::Bitmapが重いんですかね。GDI::DDBにGDI+のメソッドが使えればいいのに
No.1
- 回答日時:
GDI+を使ったことはありませんが、下記の(1)か(2)の方法で描画速度を上げられると思います。
(1)
case WM_MOVE:でのInvalidateRectをやめ、代わりにonscreenにもoffscreenと同じ線描画を行う。
(2)
case WM_MOVE:でのInvalidateRectで更新する領域をposPts.x, posPts.y, pts.x, pts.yの範囲にする。
case WM_PAINT:で更新を必要とする領域を取得(PAINTSTRUCT)し、その領域のみを再描画する。
回答ありがとうございます。
描画中のちらつきは避けたかったので1の方法は用いずに2の方法を試したところかなり速度が向上しました。
GDIの描画処理自体も相当鈍重ですが画面の更新も結構リソース食うんですね
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
[VB.net] DataGridViewの列ヘッ...
-
MFCタブコントロールのグラデー...
-
pset関数について
-
Form1 Load で実行されない。
-
VB6,リストボックスの特定行の...
-
ウインドウサイズを変更しても...
-
DirectXとGDIの違い
-
MFCでOnPaintのタイミング
-
word
-
逐次的なグラフ表示の方法
-
WM_PAINTとBitBlt
-
GDI+で高速な描画
-
Minecraft 統合版(PC)の描画距...
-
.net の ImageList について
-
文字の行間
-
ワードの図形で重なり部分の色...
-
ダイアログベースの再描画について
-
CStaticコントロールの静的イメ...
-
win32api 画面のちらつき
-
「アイテムは収集されました」...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
[VB.net] DataGridViewの列ヘッ...
-
word
-
google Colabでmatplotlibの描...
-
panelのスクロール表示について
-
VB.netでのライン描画方法がわ...
-
VB6,リストボックスの特定行の...
-
UpdateData( FALSE); による文...
-
TextBoxに文字を書いても表示さ...
-
CStaticコントロールの静的イメ...
-
VBAにGDI+を参照させる方法
-
MFCでOnPaintのタイミング
-
InvalidateRectの使い方について
-
VC++プログラムをつかったBMP画...
-
GetGlyphOutline() ご利用経験...
-
NVIDIAのシェーダーキャッシュ
-
Form1 Load で実行されない。
-
FlexGridの一部のみ表示を更新...
-
C#のタブコントロールについて...
-
WM_SIZEとWM_SIZINGの違い (Win...
おすすめ情報