- PR -

LockBitsの処理が重い(C#)

投稿者投稿内容
満月
会議室デビュー日: 2007/10/18
投稿数: 12
投稿日時: 2007-10-18 14:16
画像表示の仕方が多彩になるようなプログラムを作成しているのですが、
処理が重すぎて困っています。
3枚の画像600×800(カラー・モノクロ・透明)があるのですが、
モノクロの明度をみて、カラー画像の色を透明画像に移していくというものです。

このSetPixcelメソッドの処理が重いのですが、なにかアドバイス等いただけないでしょうか、よろしくお願いいたします。


コード:
private void SetPixcel() 

{
for(int z=0; z <= 255; z++)
{
if (z > 0)
{
bmpDate2 = base1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
check = true;
}
for(int a = 0; a < bytes; a=a+4)
{

if (rgbVlues3[a] == z)  //同明度のところを描く
{
rgbVlues2[a] = rgbVlues[a];
rgbVlues2[a+1] = rgbVlues[a+1];
rgbVlues2[a+2] = rgbVlues[a+2];
rgbVlues2[a+3] = rgbVlues[a+3];
}

}

System.Runtime.InteropServices.Marshal.Copy(rgbVlues2,0,ptr2,bytes);
base1.UnlockBits(bmpDate2);
check = false;
Application.DoEvents();
Invalidate();
//System.Threading.Thread.Sleep(50);
}
}



[ メッセージ編集済み 編集者: 満月 編集日時 2007-10-18 23:01 ]
IIJIMAS
ベテラン
会議室デビュー日: 2006/12/06
投稿数: 77
投稿日時: 2007-10-18 16:25
もしかして、ビルドした後のexeを直接エクスプローラから起動すると速かったりしませんか。
Visual Studioからの起動でも速くしたい場合は、
プロジェクトプロパティの「デバッグ」タブの
「Visual Studio ホスティング プロセスを有効にする」
のチェックをはずして試してみるとかどうでしょうか。
満月
会議室デビュー日: 2007/10/18
投稿数: 12
投稿日時: 2007-10-18 17:12
お答えいただいてありがとうございます
ビルドした後のexeを直接起動させてみると、若干早くなった気はしますが、
まだ遅いようです。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-10-18 17:29
引用:

満月さんの書き込み (2007-10-18 14:16) より:
このSetPixcelメソッドの処理が重いのですが、なにかアドバイス等いただけないでしょうか、よろしくお願いいたします。



重いも何も、このコードが何をしてるのか全く分かりません。
意味のない部分がたくさんあるし、
変数の型もわからないし、LockBitで得られたポインタを使ってないし。
高速化しようとした後も見えません。

適当に編集してありませんか?

きちんとしたコードでないと、
まともなアドバイスはできませんが、
とりあえず以下のことに気をつけてみてください。

・意味の無いコードは記述しない
・無駄に何回もLockBitしない。
・無駄に何回もApplication.DoEventしない。
・無駄に何回もInvalidateしない。
満月
会議室デビュー日: 2007/10/18
投稿数: 12
投稿日時: 2007-10-18 18:12
(編集しなおしました)

説明不足で申し訳ありません。不足していたと思われたコードを追加しました。
高速化、というのは基本的にどういうことに気をつけておけばいいのでしょうか。

このプログラムでやりたいことは、
カラー・グレースケール(255色)・透明の3枚の画像を使用して。
グレースケール画像の色を見て、黒(0)→白(255)の順にカラー画像を透明画像に移(表示)していくというものです。(256枚のパラパラアニメのような感じでしょうか)
例えば、グレースケール上では明度が5の所をカラー画像の同じところにある色を透明画像に描画し、次は明度6の所…といった風に

コード:
private void Set() 

{
BitmapData bmpDate, bmpDate2, bmpDate3;
bmpDate2 = base1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
bmpDate = mat.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
bmpDate3 = effe.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
bytes = w * h * 4;

IntPtr ptr = bmpDate.Scan0;//カラー画像
byte[] rgbVlues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbVlues, 0, bytes);

IntPtr ptr2 = bmpDate2.Scan0;//透明画像
byte[] rgbVlues2 = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr2, rgbVlues2, 0, bytes);

IntPtr ptr3 = bmpDate3.Scan0;//グレースケール画像
byte[] rgbVlues3 = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr3, rgbVlues3, 0, bytes); //byte型の変数にビットマップの情報を代入
effe.UnlockBits(bmpDate3);
mat.UnlockBits(bmpDate);

//ココから以降が重いようです。

for(int z=0; z <= 254; z++)  //明度0〜255
{
bool byouga = false;
bmpDate2 = base1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); //画像をロックする

for(int a = 0; a < bytes; a=a+4)  
{
if (rgbVlues3[a] == z)  //同明度のところを描いていく
{

rgbVlues2[a] = rgbVlues[a]; //B
rgbVlues2[a+1] = rgbVlues[a+1]; //G
rgbVlues2[a+2] = rgbVlues[a+2]; //R
rgbVlues2[a+3] = rgbVlues[a+3]; //アルファ値
byouga = true;
}
}

System.Runtime.InteropServices.Marshal.Copy(rgbVlues2, 0, ptr2, bytes);
base1.UnlockBits(bmpDate2);

if (byouga == true)
{
Application.DoEvents();
Invalidate();
}
       System.Threading.Thread.Sleep(10); //ウェイト
}
}




[ メッセージ編集済み 編集者: 満月 編集日時 2007-10-18 23:01 ]

[ メッセージ編集済み 編集者: 満月 編集日時 2007-10-19 00:12 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-10-18 18:46
後で書こうと思っていたけど、やっぱ今書こう。


頼む
日本語で説明してくれ


コードの1つ1つ、何をしたいのか、説明してください。
読み手に、解読の負担を強いないでください。

解読の負担をかけるということは、読んでもらえない可能性を高めます。
それでも読んでくれる人はいるでしょうが、回答を得る機会を自ら減らしているのではないでしょうか。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-10-18 18:50
引用:

満月さんの書き込み (2007-10-18 18:12) より:
説明不足で申し訳ありません。不足していたと思われたコードを追加しました。
高速化、というのは基本的にどういうことに気をつけておけばいいのでしょうか。



細かいテクニックはいろいろあるでしょうが。

全ての言語で共通して最も重要なことは
とにかくループの深さを減らすことです。
その後、一番深いループから順に、
深いループの処理をより浅いループに移せないか検討します。

言葉では非常に簡単ですが、重要で、奥が深く、
高速化はこれが全てと言ってもいいくらいです。

コードはざっと眺めただけですが、
満月さんのコードはたぶん2重のループがあり、
一番深い部分はw*h*256回だけ回ることになります。
これをw*h回に減らせると思います。

これで、およそ256倍早くなる、とは言えませんが、
たぶん100倍くらいは早くなります。

他にもいろいろ早くできるポイントはありますが、
とりあえずそれで十分ではないでしょうか。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-10-18 18:56
引用:

Jittaさんの書き込み (2007-10-18 18:46) より:
それでも読んでくれる人はいるでしょうが、回答を得る機会を自ら減らしているのではないでしょうか。



読んじゃいましたが、
やっぱめんどくさかったです。
放棄しようかと思いましたが、
最初に答えてしまったので。

引用:

コードの1つ1つ、何をしたいのか、説明してください。
読み手に、解読の負担を強いないでください。



高速化したいってことなんで、
コードが重要なんですよね。

更に言うと、
コードがきちんとインデントされてるといいんですがね。
今回はインデントされてれば問題点が一目瞭然かと。

スキルアップ/キャリアアップ(JOB@IT)