DOBON.NET DOBON.NETプログラミング掲示板過去ログ

画像の貼り付け

  • 題名: 画像の貼り付け
  • 著者: mimi
  • 日時: 2006/08/05 15:26:29
  • ID: 17013
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
分類:[.NET]

2006/08/05(Sat) 18:45:44 編集(投稿者)

画像を
32*32の大きさでタイルのように貼り付けるのですが
これを最大化して張り付けると
横に40縦に30ぐらいの32*32の大きさの画像を貼り付ける事になるのですが
どうしても遅くなります
たとえば再描画を要求するときとか遅くなってしまいます

//マップの縦の数だけ繰り返す
for (int y = 0; y < mapy_kazu; y++)
{
//マップの横の数だけ繰り返す
for (int x = 0; x < mapx_kazu; x++)
{


//画像を表示する座標
Rectangle dest = new Rectangle(x * tip_width, y * tip_height, tip_width, tip_height);


//表示する画像を切り取る座標
Rectangle src = new Rectangle(0, 0, tip_width, tip_height);

//画像の表示
g.DrawImage(img, dest, src, GraphicsUnit.Pixel);
}
}

このようになっていますがもう少し高速化したいのですが何か
いいてはないでしょうか?
>このようになっていますがもう少し高速化したいのですが何か
>いいてはないでしょうか?

古典的な手法である「オフスクリーン」を使うのがいいと思います。

具体的には、最大描画サイズと同じ大きさのビットマップを用意して、アプリ都合による再描画はそれに対して行います。

そして、Pain イベントなどのシステム都合の再描画では、↑のビットマップ1枚を DarawImage するだけで済まします。
2006/08/05(Sat) 20:18:27 編集(投稿者)
2006/08/05(Sat) 20:18:25 編集(投稿者)

//メインフォームの描画処理
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
MapPaint(g);

}


//マップの描画処理
private void MapPaint(Graphics g)
{

Image img = form3.getImage();

if (img != null)
{

Image img1 = new Bitmap(MapxPaint_Size, MapyPaint_Size);
Graphics buf = Graphics.FromImage(img1);


//マップの縦の数だけ繰り返す
for (int y = 0; y < mapy_paint; y++)
{
//マップの横の数だけ繰り返す
for (int x = 0; x < mapx_paint; x++)
{


//画像を表示する座標
Rectangle dest = new Rectangle(x * tip_width, y * tip_height, tip_width, tip_height);


//表示する画像を切り取る座標
Rectangle src = new Rectangle(0, 0, tip_width, tip_height);

//画像の表示
buf.DrawImage(img1, dest, src, GraphicsUnit.Pixel);
}
}


g.DrawImage(img, 0, 0);

}
}

このようにオフスクリーンバッファをやったのですが
前回と同じくらい遅くなってしまいうまくいきません
描画のたびに毎回オフスクリーンバッファに描画するのは無駄が大きいでしょう。ただでさえ Graphics.DrawImage は遅いのに。
画像に変更があった時にバッファのその部分を書き換え、OnPaint ではその作成済みバッファをコントロールに描画するだけにするようにしましょう。
もしかすると質問の意図をつかめておらず,見当はずれなことかもしれませんが...

タイル状に貼り付ける画像はすべて同じものですか?
同じものをタイル状に表示するだけならFormやPictureBoxのBackgroundImageに指定すればよいと思います。
違うものであってもすべて異なるのではなく,パターンがあるのならパターンの最小単位のビットマップを作成して,やはりBackgroundImageに指定すればよいのではないでしょうか?
パターンというか
自分はマップエディタをつくっているのですが
たとえばクライアントサイズが640*480でチップの大きさが32*32
のときは横に20個縦に15個チップが並びますから
ここで640*480のオフスクリーンを作りそこにマップを読み込みます
そのあとクリックした部分に画像を貼り付けるのですが
その部分だけオフスクリーンのその部分だけ変更すればいいのですか
またウィンドウを最大化したりしてクライアント領域が変化するとき
はどうしたらいいでしょうかこのときはオフスクリーンを変更したサイズ
にまた作り直すのですか?
つまり横にウィンドウをドラッグしたら横のクライアントサイズが変わりますよね
横が600ぐらいになったとしたら
ウィンドウの大きさが変更しているときは
つねにすべてチップをオフスクリーンに書き直さなくてはいけないのでしょうか
それとも変更した大きさの部分だけ書き直すことはできますでしょうか
今回の場合横サイズが600だから600-480で横幅120ピクセルだけチップを追加する
ことはできるでしょうか?
たとえばクライアントが640*480のとき最大化するとクライアント領域が
大きくなりますがこのとき最大化するまでが遅くなります
マップエディタでしたか。
それでは見当違いも甚だしいことを書いてしまいました。すみません。

それでしたらオフスクリーンにWinAPIのBitBltなどでバッファを作成するように
すればよいと思います。Graphics.DrawImageはちょっと遅いと思います。

>つねにすべてチップをオフスクリーンに書き直さなくてはいけないのでしょうか

いいえ,それではどうしても遅くなってしまうと思います。
Hongliangさんもお書きになっているように,変更のあった部分だけを描画する
ようにします。そのため,どこが変更されたのかというのを自分で管理する
必要があります。

ただ,ウィンドウの大きさの変更のたびにバッファの大きさを変えていては大変
なので,メモリに余裕があるならば,最大サイズでバッファを作成しておき,
その一部分を切り取って表示するようにすればよいと思います。これもどこを表示
しているのかというのを自分で管理する必要があります。
ありがとうございます
あとスクロールバーでサイズに治まりきらない画像を表示させるのですが
クライアントサイズが640*480でスクロールバーの横をクリックすると
横のチップサイズ分移動させたいのですが
このときは前回表示されていなかった隠れていた部分つまり新しく表示された部分だけオフスクリーンに書き換えればいいのでしょうか?それと横にスクロールされると言う事はスクロールされた分だけ
表示されなくなる部分がありますがこれをオフスクリーンから消すにはどうしたら
いいのでしょうか?
  • 題名: Re[8]: 画像の貼り付け
  • 著者: YAS
  • 日時: 2006/08/07 7:21:01
  • ID: 17030
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
>表示されなくなる部分がありますがこれをオフスクリーンから消すにはどうした
>らいいのでしょうか?
どうしたら「いい」のかは難しく,いろいろな方法があると思います。求めている速度や,実行する環境にもよりますが,「わたしだったら」,オフスクリーンでBitBltを使ってまず全画面をスクロール分移動させ,次に足りない部分を描画します。そしてスクリーンに転送します。
当然それほど速い処理とはいえませんので,速度が足りなければ別の方法を考えます。

DOBON.NET | プログラミング道 | プログラミング掲示板