C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: 複数の画像を連続して描画する方法


(過去ログ 99 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■59100 / inTopicNo.1)  複数の画像を連続して描画する方法
  
□投稿者/ B/B (1回)-(2011/05/13(Fri) 15:19:45)

分類:[C#] 

初めまして。RPGツクールのような簡単な2Dマップエディタを作ろうとC#を使い始めたのですが、画像の扱いでわからないことがありますので質問させていただきます。

開発ツールはVisualStudio2010、言語はC#で行っております。

今やりたいことは、16x16のチップを縦横それぞれに100チップ並べた画像(サイズは1600x1600になる)をフォーム上のPictureBoxに描画し、スクロールしたり拡大縮小(ズーム)できるようにすることです。

実際に、それができるように試してはみたのですが、拡大縮小(ズーム)したときや、ウィンドウを最大化したときに、動作が重くなり、(縦横のチップの多さが多いほど)少しの時間固まります。
以下のようにして、pictureBox1_paintのなかで描画処理をしました。
for (float xi = 0; xi < 100; xi++)
for (float yi = 0; yi < 100; yi++)
e.Graphic.DrawImage(img, GetChipPos(xi, yi), GetChipRect(data[(int)xi, (int)yi, 0]), GraphicsUnit.Pixel);
※GetChipPosはチップを描画する座標(四隅)を指定しRectを返す関数、GetChipRectはチップの集まりから描画するチップを指定しRectを返す関数です。

しかし、チップを並べるのではなく、代わりに1600x1600の一枚絵でやってみると、ほとんど固まることはなく拡大縮小などがスムーズにできました。

おそらく、複数の画像を連続して描画する方法自体、効率が悪いのだと思うのですが、
これを解決するような方法があれば教えてください。
引用返信 編集キー/
■59102 / inTopicNo.2)  Re[1]: 複数の画像を連続して描画する方法
□投稿者/ やじゅ (1899回)-(2011/05/13(Fri) 16:27:29)
やじゅ さんの Web サイト
No59100 (B/B さん) に返信
> おそらく、複数の画像を連続して描画する方法自体、効率が悪いのだと思うのですが、
> これを解決するような方法があれば教えてください。

Bitmapオブジェクトの作成してから、PictureBoxにセットするようにする。
「Bitmapオブジェクト生成 C#」のキーワードで検索してみるとか。

引用返信 編集キー/
■59120 / inTopicNo.3)  Re[1]: 複数の画像を連続して描画する方法
□投稿者/ くり太郎 (20回)-(2011/05/14(Sat) 17:19:19)
くり太郎 さんの Web サイト
No59100 (B/B さん) に返信
> 以下のようにして、pictureBox1_paintのなかで描画処理をしました。

恐らく、これが問題なんだと思います。
Paint イベントは Control オブジェクトのイベントで、コントロールが再描画される都度実行されます。
つまり、コントロールのコンテナであるウィンドウサイズが変更される度に再描画されていることになります。

描画するタイミングや、別のイベントを検討してみるのがいいでしょう。
引用返信 編集キー/
■59130 / inTopicNo.4)  Re[2]: 複数の画像を連続して描画する方法
□投稿者/ PATIO (112回)-(2011/05/16(Mon) 15:54:09)
結局、実際に画面に対して描画してしまうと
その度に画面への反映(表示しようとする)が走ってしまう為に
時間が掛かっていると言う事だと思います。
一般的に描画処理を大量に行う場合のパフォーマンス確保の方法として
画面に直接描画するのではなく、表示されるイメージをメモリ上で
作成してからそのイメージを画面に反映すると言う方法をとります。
これがやじゅさんが書かれている方法ですね。

あと、実際の表示イメージが変わるわけではなくて
表示の倍率とか表示される範囲が変わるだけと言う話なら
毎回、イメージの作成をやり直す必要はないはずですよね。
イメージの変更が必要ないなら作成済みのイメージを
メモリ上に保持して置いてそれを画面に反映する時に
拡大縮小したり、必要な範囲を転送したりする方が
同じ処理を何回もしなくて済みます。

パフォーマンスを上げる考え方の基本は
重い処理は出来る限り処理回数を減らせないか検討する。
一度行なっておけば、使い回せるものは使い回せるように
処理を組み立てると言う事だと思います。
ちなみに画面に反映する(表示する)と言う処理はかなり重い処理です。

引用返信 編集キー/
■59205 / inTopicNo.5)  Re[3]: 複数の画像を連続して描画する方法
□投稿者/ B/B (2回)-(2011/05/19(Thu) 10:09:47)
やじゅ様、くり太郎様、PATIO様、ご回答ありがとうございます。
皆様のご意見を参考に、以下のように処理を変更することで望んでいた通り処理がスムーズになりました。

/* 初期処理 */
//マップサイズに合わせたBitmap変数を作成
map = new Bitmap(100 * 16, 100 * 16);
//BitmapからGraphicクラスの作成
g = Graphics.FromImage(map);
//マップ画像の作成
for (int xi = 0; xi < 100; xi++)
for (int yi = 0; yi < 100; yi++)
g.DrawImage(img, GetChipPos(xi, yi), GetChipRect(data[(int)xi, (int)yi, 0]), GraphicsUnit.Pixel);

/* paint関数 */
pictureBox1.Width = (int)(100.0 * 16.0 * zoom);
pictureBox1.Height = (int)(100.0 * 16.0 * zoom);
e.Graphics.DrawImage(map, 0, 0, pictureBox1.Width, pictureBox1.Height);

なぜ、Graphic変数"g"に描画しているのに実際にpictureBoxに描画する際にはBitmap変数"map"を指定するだけでいいのかが分かりませんが。
しかしとりあえずこれで問題は解決できました。皆様ありがとうございました。

上の方法でも何か問題があればご指摘くださるとありがたいです。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -