- PR -

LockBitsの処理が重い(C#)

投稿者投稿内容
k_kazu
常連さん
会議室デビュー日: 2006/02/11
投稿数: 25
投稿日時: 2007-10-19 08:33
unsafe {} を使って直接ポインタアクセスをすると
LockBits して配列コピーするよりも4倍早いそうです。

参考URL:
「C#(GDI+) : Bitmap の内部色データにアクセスする (1)」
http://junki.lix.jp/csgr/002ColorDataAccess1.htm

満月
会議室デビュー日: 2007/10/18
投稿数: 12
投稿日時: 2007-10-19 16:51
引用:

れいさんの書き込み (2007-10-19 02:02) より:

なら、確保もコピーも32bit=1 UInt32単位でやったらどうですか?
ということです。

コード:

IntPtr ptr = bmpDate.Scan0;//カラー画像
UInt32[] rgbVlues = new UInt32[w*h];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbVlues, 0, rgbVlues.Length);





ありがとうございます! 
参考にさせていただいた結果かなり早くなりました!^^

UInt32[]型で作成した結果なのですが、次のようなエラーがでてしまいました。

Marshal.Copy(int[], int, System.IntPtr, int)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。
エラー CS1503: 引数 '1': 'uint[]' から 'int[]' に変換できません。

代わりにInt型(32ビット符号付)で作成してみて描画されたのですが、今までのアニメとは少し違った動きをするようになってしまいました。
描画されるビットが飛んでいるようで、(最終的にはすべて描画されますが)

コード:

int型のとき  rgbVlues[0] -13063450

byte型のとき rgbVlues[0]  230 B
rgbVlues[1]  170 G
rgbVlues[2]  56 R
rgbVlues[3]  255 アルファ


同じ画像で1ピクセル目のint、byte型の情報なのですが、
int型とbyte型の時にはなにか配列に入るピクセルの順番が違ったり、するのでしょうか?
int型の-13063450というのはどういう経緯でそんな数字になっているのでしょうか…

すみません、調べてみたのですが、見つけることが出来ませんでした、もしよろしかったら御教授いただけますでしょうか、よろしくお願いいたします。


引用:

k_kazuさんの書き込み (2007-10-19 08:33) より:
unsafe {} を使って直接ポインタアクセスをすると
LockBits して配列コピーするよりも4倍早いそうです。


そんな方法もあるのですね、ありがとうございます!
現在試している方法でダメだったら、試してみます!

[ メッセージ編集済み 編集者: 満月 編集日時 2007-10-19 17:04 ]
seai
ベテラン
会議室デビュー日: 2007/04/10
投稿数: 60
投稿日時: 2007-10-22 16:12
こんにちは
引用:

満月さんの書き込み (2007-10-19 16:51) より:
代わりにInt型(32ビット符号付)で作成してみて描画されたのですが、今までのアニメとは少し違った動きをするようになってしまいました。
描画されるビットが飛んでいるようで、(最終的にはすべて描画されますが)

コード:
int型のとき 	rgbVlues[0]  -13063450

byte型のとき 	rgbVlues[0]  230  B
		rgbVlues[1]  170  G
		rgbVlues[2]  56   R
		rgbVlues[3]  255  アルファ


同じ画像で1ピクセル目のint、byte型の情報なのですが、
int型とbyte型の時にはなにか配列に入るピクセルの順番が違ったり、するのでしょうか?
int型の-13063450というのはどういう経緯でそんな数字になっているのでしょうか…

すみません、調べてみたのですが、見つけることが出来ませんでした、もしよろしかったら御教授いただけますでしょうか、よろしくお願いいたします。




数字の経緯ですが以下の内容ではないでしょうか。

int32型とuint32型は数値の取りうる範囲が異なります。
int32型の数値は、最上位ビットがプラスかマイナスかを表す
符号になります。(表せる数値としては31ビット)
int32 0x80000000〜0x7fffffff
uint32 0x00000000〜0xffffffff

従って、ご提示のbyte型数値をint32型に当てはめると
230→0xe6
170→0xaa
56 →0x38
255→0xff
なので
0xff38aae6(1111 1111 0011 1000 1010 1010 1110 0110B)
になります。
この数値は最上位ビットが1ですからint型では負の数値になります。
負の数値は1の補数をとれば求めることができます。
1の補数とは数値を構成する各ビットを反転し1を加えたものです。
(元の数値と加算するとオーバーフローを伴って0になる)
簡単にするためint8の場合を考えます。
0x01(0000 0001)=1、0x02(0000 0010)=2、、、ですので
まずそれぞれのビットを反転(1と0を逆にする)します。
0xfe(1111 1110)、0xfd(1111 1101)
となりますのでそれぞれに1を足します。
0xff(1111 1111)=-1、0xfe(1111 1110)=-2
となります。
ご提示の数値は負の数値ですから逆の手順で1を引いて
各ビットを反転すれば数値が求められます。
0xff38aae6(1111 1111 0011 1000 1010 1010 1110 0110B)
の場合は
1を引いて、
0xff38aae5(1111 1111 0011 1000 1010 1010 1110 0101B)
ビットを反転して
0x00c7551a(0000 0000 1100 0111 0101 0101 0001 1010B)
=13063450
ですので、先頭にマイナスをつければ
ご提示の数値になります。

int32でご提示の数値を表現するとrgbVlues[3]アルファの
値しだいで、負の数値をとることがありますので
それが動作に影響を与えていることは無いでしょうか?

ご参考になれば幸いです。

満月
会議室デビュー日: 2007/10/18
投稿数: 12
投稿日時: 2007-10-23 18:00
引用:

seaiさんの書き込み (2007-10-22 16:12) より:

int32でご提示の数値を表現するとrgbVlues[3]アルファの
値しだいで、負の数値をとることがありますので
それが動作に影響を与えていることは無いでしょうか?

ご参考になれば幸いです。



ありがとうございます! 非常に参考になりました!
おかげさまでビットがとんだ理由もわかり、スピードも速くなりました!!

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