
趣味でC#を使ってWindows Forms Applicationでツールを制作している者です。
Windows10環境でVisual Studio2019を使用しています。
今制作しているツールでは、デスクトップをキャプチャしてForm上のPictureBoxに表示し、マウスドラッグで選択範囲(ラバーバンド)を描画してトリミングする機能を実装しました。
しかしPictureBoxに表示した画像サイズが大きいと描画処理が非常に重くなりカクカクになります。
これは、Graphicsオブジェクトに背景画像を描画してラバーバンドのためにラインを4回描画して合成してPictureBoxに表示する‥ということを毎フレームCPUで行っているからでしょうか?
試しに、最初にGraphicsオブジェクトに背景画像を描画する部分を省くと非常に快適になりますが、引いたラインが残って多重に重なっていってしまうため、やはり毎フレームラインを引く前の状態に戻す必要はあると思っています。
その場合なるべく易しい(本職がプログラマでも無い私でも対処可能な)解決法は無いでしょうか?
GeForce GTX970が入ったマシンで使う想定なので、OpenCLでGPUに処理させれば良いのでしょうか。
ツール制作スキルとしてはよくある実装をDobon.Netにお世話になりながら実装ができる程度のレベルですが、何かライブラリを入れて関数を利用すれば良いくらいなら何とかできそうには思います。
よろしくお願いします。m(_ _)m

No.1ベストアンサー
- 回答日時:
深く考えていません(単なる思い付きです)
一から描画するのではなく、一度PictureBoxの範囲を保存しておいて、それを上書きとかできないんでしょうか?
速いかどうか私にはわかりませんが。
それともラバーバンドを引く前にその部分の背景を保存して置き、ラバーバンドが移動すれば、保存しておいた背景部分(ラバーバンドのあった部分だけのデータ)を上書きするとか。
kihonkanaさんご回答ありがとうございます!
それぞれのご提案、とても参考になりました。
>一から描画するのではなく、一度PictureBoxの範囲を保存しておいて、それを上書きとかできないんでしょうか?
>速いかどうか私にはわかりませんが。
こちらPictureBoxを2枚重ねてフォームに配置しておいて、背景画像用とラバーバンド描画用に分けてマウスドラッグ中はラバーバンドの描画のみ行うようにしたら、1920*1080の画像でもかなり軽くなりました!
>それともラバーバンドを引く前にその部分の背景を保存して置き、ラバーバンドが移動すれば、保存しておいた背景部分(ラバーバンドのあった部分だけのデータ)を上書きするとか。
大きな範囲でラバーバンドを作成した際には効果が薄いかな?と最初は思ったのですが、ラバーバンドの上下左右のライン4つの矩形部分のみ描画して合成する形にすることでかなり処理速度が上がりそうに思いました‥!
現状で厳しくなった場合にぜひ試してみたいと思います。
No.2
- 回答日時:
Windows Formなのが原因かと思います。
Windows Formは元々Delphiに由来しWindows 98等まだまだグラフィックボードと言えばただビットマップに変換しているだけの時代のライブラリです。
ところが現在のWindowsは殆どの画面表示をDirect X経由でGPUが行う構成になっています。
そのためラバーバンドしようとするとGPUがウィンドウをレンダリング→CPUへもってきて加工→GPUが再度ウィンドウをレンダリングという流れになります。
加えてWindows FormはレンダリングのGPU化が不完全でGPUが再度ウィンドウをレンダリングする時にCPU側からかなりの支援を行っています。
解決策としてはWPFを使うというのが手軽だと思います。
WPFはDirect Xにウィンドウやフォントのサイズなどパラメータだけ送ってレンダリングもアンチエイリアシングも全てGPUにお任せです。
加えてラバーバンドもGPUがレンダリングした結果から切り出してそのまま表示先にGPU上ではめ込み合成されます。
izayoimizukiさんご回答ありがとうございます!
なるほど‥とても分かりやすい解説で納得しました。
確かに色々とツールを作るにつれ、限界を感じる場面が増えてきました。
GPUを活かしてくれないのもそうですし、標準のコントロールで可能なカスタマイズの範囲も狭く、特にUIの見た目のプロパティが少なすぎて‥
書籍やネットの情報の少なさからWPFに手を出すかどうかずっと悩んでいたのですが、これを機に勉強を始めてみたいと思います‥!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
[VB.net] DataGridViewの列ヘッ...
-
TextBoxに文字を書いても表示さ...
-
Minecraft 統合版(PC)の描画距...
-
word
-
C# ラバーバンドの描画を快適に...
-
panelのスクロール表示について
-
VB6,リストボックスの特定行の...
-
google Colabでmatplotlibの描...
-
リストビューでのドラッグ&ド...
-
画面リサイズ時のちらつきをな...
-
MFC ビットマップ描画で残像が残る
-
iPhoneアプリで作成したアプリ...
-
NVIDIAのシェーダーキャッシュ
-
CS_HREDRAW|CS_VREDRAWについて
-
重いグラフィックス処理
-
win32api 画面のちらつき
-
GDI+で高速な描画
-
GDI+について
-
[Win32API]JpegをDIBに変換する
-
矢印を描画するには
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
[VB.net] DataGridViewの列ヘッ...
-
word
-
TextBoxに文字を書いても表示さ...
-
panelのスクロール表示について
-
google Colabでmatplotlibの描...
-
MFCでOnPaintのタイミング
-
CStaticコントロールの静的イメ...
-
VBAにGDI+を参照させる方法
-
Form1 Load で実行されない。
-
InvalidateRectの使い方について
-
CScrollViewの使用方法について
-
GDI+について
-
VC++プログラムをつかったBMP画...
-
ウインドウサイズを変更しても...
-
VB6,リストボックスの特定行の...
-
タブをオーナードローすると、...
-
ビットマップを表示させる(MFC)
-
UpdateData( FALSE); による文...
-
C++にて、塗りつぶされた円を描...
おすすめ情報