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

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

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

Re[7]: WPFでの画像処理のための画像の読み込みと書き込み


(過去ログ 86 を表示中)

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

■51065 / inTopicNo.1)  WPFでの画像処理のための画像の読み込みと書き込み
  
□投稿者/ harukaze96 (1回)-(2010/06/24(Thu) 09:39:45)

分類:[C#] 

C#のWPFで画像処理のプログラムを書いているのですが,分からないことが,2つあります.

(質問1)
bitmap以外のファイルのピクセルの情報が取って来れずに困っています.

bitmap場合,以下の手順でピクセル情報を取ってこれるんですが....
Uri tempUri = new Uri(this.PropMyOpenDialog.FileNames[i], UriKind.RelativeOrAbsolute);
BitmapDecoder myBitmapDecoder = BitmapDecoder.Create(tempUri, BitmapCreateOptions.None, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
data = target.CopyPixels(
this.mData, //格納先
this.mPixelWidth * this.mChanelNum, //スライド
0 //オフセット
);

たとえば,jpegの場合,
以下のどちらのコードを書いてもbyteの配列の値が全て「255」になってしまいます.
何が足りないのでしょうか??

//サンプル1
Uri tempUri = new Uri(this.PropMyOpenDialog.FileNames[i], UriKind.RelativeOrAbsolute);
BitmapDecoder myBitmapDecoder = JpegBitmapDecoder.Create(tempUri, BitmapCreateOptions.None, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
data = target.CopyPixels(
this.mData, //格納先
this.mPixelWidth * this.mChanelNum, //スライド
0 //オフセット
);

//サンプル2
Uri tempUri = new Uri(this.PropMyOpenDialog.FileNames[i], UriKind.RelativeOrAbsolute);
JpegBitmapDecoder myJpegBitmapDecoder = new JpegBitmapDecoder(tempUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myJpegBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
data = target.CopyPixels(
this.mData, //格納先
this.mPixelWidth * this.mChanelNum, //スライド
0 //オフセット
);

(質問2)
ピクセルの情報をbitmapファイルとして書き出す場合に,BitmapSource.Createの引数strideで指定する値が分かりません.
32bitの場合
(PixelWidth * mPixelFormats.Bgr32.BitsPerPixel + 7) / 8
と指定すれば,正常に書き出せるのですが,
(PixelWidth * mPixelFormats.Bgr24.BitsPerPixel + 7) / 8
24bitの場合正常に書き出されません.
ビットマップのストライドって,「1行分の幅のbyte数が4で割り切れるように,幅のバイト数に余分なbyteを足したもの」ですよね?

質問は以上の2つです.
よろしくお願いします!!




引用返信 編集キー/
■51072 / inTopicNo.2)  Re[1]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ Hongliang (654回)-(2010/06/24(Thu) 11:37:29)
2010/06/24(Thu) 11:39:24 編集(投稿者)

> ビットマップのストライドって,「1行分の幅のbyte数が4で割り切れるように,幅のバイト数に余分なbyteを足したもの」ですよね?
これは合っています。

> 32bitの場合
> (PixelWidth * mPixelFormats.Bgr32.BitsPerPixel + 7) / 8
> と指定すれば,正常に書き出せるのですが,
> (PixelWidth * mPixelFormats.Bgr24.BitsPerPixel + 7) / 8
> 24bitの場合正常に書き出されません.
// 32bpp の場合、1 ピクセルが 32bits = 4bytes ですから、必ず一行のバイト数は 4 で割り切れます。計算する必要もありません。
そもそも、BitsPerPixel は文字通りピクセル辺りのビット数を返します。32bpp なら 32 ですし、24bpp なら 24 です。
(x + 7) / 8
と言う式は、x を 8 単位で切り上げ、それを 8 で割った値にします。x が 1 〜 8 なら 1、x が 9 〜 16 なら 2 です。stride は 4 の倍数でなければならないのに、普通に 1 とか出てくるのはおかしいですよね?

まず、横方向のビット数は PixelWidth * BitsPerPixel で求まります。横 1px で 24bpp の場合 24bits です。
4bytes は 32bits ですから、横方向のビット数を 32bits の倍数に切り上げます。
で、最後にビット数からバイト数に単位を変えます。
切り上げは先ほどの式のように +*/ で表現することもできますが、その式の意味が分からないなら、剰余演算 % を使って計算することもできます。

あと、PixelFormat.Bgr24 などを直接使うのではなく、BitmapSource の Format プロパティを使うべきだと思います。

> byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
チャンネル? 必要なバイト数は stride * 高さで十分です。

> data = target.CopyPixels(
> this.mData, //格納先
> this.mPixelWidth * this.mChanelNum, //スライド
> 0 //オフセット
> );
BitmapSource.CopyPixels は返値を持ちませんが……。
引用返信 編集キー/
■51083 / inTopicNo.3)  Re[2]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ harukaze96 (2回)-(2010/06/24(Thu) 15:34:07)
Hongliangさん
回答ありがとうございます!!

>あと、PixelFormat.Bgr24 などを直接使うのではなく、BitmapSource の Format プロパティを使うべきだと思います。
へー,知りませんでした.次からそうします!!


(質問1)ですが,
教えてくれたことは,理解できたのですが,まだ,上手くいきません

式は
stride = PixelWidth * BitsPerPixel;
stride = ((32 - stride%32) + stride)/8;
であっているでしょうか??

たとえば,
600*600でRGBの画像の場合だと,ストライドはどうなるのでしょうか??


あと,

> BitmapSource.CopyPixels は返値を持ちませんが……。
すいません.書き間違えました.
(質問1)
data = target.CopyPixels(
mData, //格納先
this.mPixelWidth * this.mChanelNum, //ストライド
0 //オフセット
);


回答よろしくお願いします!!
引用返信 編集キー/
■51084 / inTopicNo.4)  Re[3]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ Hongliang (656回)-(2010/06/24(Thu) 16:05:42)
> 式は
> stride = PixelWidth * BitsPerPixel;
> stride = ((32 - stride%32) + stride)/8;
> であっているでしょうか??
これだけでは stride % 32 が 0 だったとき余計な 4 が足されてしまうので、条件判断で除く必要があります。

> たとえば,
> 600*600でRGBの画像の場合だと,ストライドはどうなるのでしょうか??
横幅のピクセル数が 4 の倍数の場合、単純に 3 倍するだけでいいので 1800 ですね。

> data = target.CopyPixels(
> mData, //格納先
> this.mPixelWidth * this.mChanelNum, //ストライド
> 0 //オフセット
> );
何か変わりました? 相変わらず返値取ってるみたいですけど。これじゃコンパイルエラーでしょう。
引用返信 編集キー/
■51178 / inTopicNo.5)  Re[4]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ harukaze96 (3回)-(2010/06/26(Sat) 17:29:53)
Hongliangさん
回答ありがとうございます!!
返事が遅くなってしまい申し訳ありません.

おかげさまで,質問2は解決しました.

で,質問1なのですが,
>何か変わりました? 相変わらず返値取ってるみたいですけど。これじゃコンパイルエラーでしょう。
またまた,書き間違えてました.
target.CopyPixels(
Data, //格納先
stride, //ストライド
0 //オフセット
);

現状では,コンパイルは通ります.
ただし,Dataに格納される値が全て「255」となってしまいます.

指摘,よろしくお願いします!!


引用返信 編集キー/
■51179 / inTopicNo.6)  Re[5]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ harukaze96 (4回)-(2010/06/26(Sat) 17:50:57)
すいません,この例じゃ意味が不明ですね.
書き直します.
以下のどちらのコードを書いてもbyteの配列の値が全て「255」になってしまいます.

//サンプル1
Uri tempUri = new Uri("Sample01.jpg", UriKind.RelativeOrAbsolute);
BitmapDecoder myBitmapDecoder = JpegBitmapDecoder.Create(tempUri, BitmapCreateOptions.None, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
myBitmapSource.CopyPixels(
 data, //格納先
 stride, //ストライド
 0 //オフセット
);

//サンプル2
Uri tempUri = new Uri("Sample01.jpg", UriKind.RelativeOrAbsolute);
JpegBitmapDecoder myJpegBitmapDecoder = new JpegBitmapDecoder(tempUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myJpegBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
myBitmapSource.CopyPixels(
 data, //格納先
 stride, //ストライド
 0 //オフセット
);


bitmapだったら,以下のコードで正しく画素の情報を取得できるんですが・・・・・

Uri tempUri = new Uri("Sample01.bmp", UriKind.RelativeOrAbsolute);
BmpBitmapDecoder myBmpBitmapDecoder = new BmpBitmapDecoder(tempUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource myBitmapSource = myBmpBitmapDecoder.Frames[0];
byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
myBitmapSource.CopyPixels(
 data, //格納先
 stride, //ストライド
 0 //オフセット
);

jpegのエンコードはどこが間違っているのでしょうか??
指摘よろしくお願いします.


引用返信 編集キー/
■51182 / inTopicNo.7)  Re[6]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ Hongliang (658回)-(2010/06/26(Sat) 20:57:39)
> byte[] data = new byte[画像の幅*画像の高さ*チャンネル数];
相変わらずここが意味不明ですが、それ以外は特に間違ってません。私のところではちゃんと取得できています。
// 元画像が真っ白なだけという可能性もありますが。
引用返信 編集キー/
■51183 / inTopicNo.8)  Re[7]: WPFでの画像処理のための画像の読み込みと書き込み
□投稿者/ harukaze96 (5回)-(2010/06/26(Sat) 22:21:55)
Hongliangさんの言う通りでした.
画素値はちゃんと取れてました・・・・・・.

>// 元画像が真っ白なだけという可能性もありますが。
完全に真っ白ってわけではなかったのですが・・・・・(白の背景に人が写っている写真)
デバッグで画素の情報を格納後に確認したとき,スクロールバーを動かして確認していたのですが,
スクロールバーを動かすのが早すぎたせいか,見落としておりました.
ありがとうございます.
おかげで,問題を解決することができました.


解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -