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

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

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

Re[9]: VB.NETでのStretchDIBitsでの画像表示


(過去ログ 69 を表示中)

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

■40410 / inTopicNo.1)  VB.NETでのStretchDIBitsでの画像表示
  
□投稿者/ AYM (9回)-(2009/08/25(Tue) 11:43:08)

分類:[VB.NET/VB2005 以降] 

2009/08/25(Tue) 12:44:20 編集(投稿者)
お世話になっております。
WindowsVista64Bit、VisualStudio2008・VB.NETにて開発しております。

画像関係のアプリケーションを開発しているのですが、.NETのGDIクラスでの画像描画では大きいサイズのファイルを描画すると
速度的な問題があり、Win32APIを使用する事になりました。

VB内でVirtualAllocを使用して確保した領域に対してデータを書き込み、DIBの情報を作成しStretchDIBits関数に渡しているのですが
戻り値・GetLastErrorの取得値が共に0となり画像が表示されません。

以下がソースになります。

Dim PicDraw as Graphics
PicDraw = PictureBox1.CreateGraphics

'// HDCの取得
Dim ImageHDC as IntPtr
ImageHDC = PicDraw.GetHDC()

'// DIB情報作成 実際の構造体はDWORD/WORDが混じっておりMarshalCopyできない為、DWORDにて統一。
Dim Bitinfo(10) as Integer

'// 構造体サイズ
Bitinfo(0) = 40
'// イメージ横サイズ
Bitinfo(1) = 400
'// イメージ縦サイズ
Bitinfo(2) = 400
'// BitCountとPlanesはWORDの為、ShiftしてDWORDに突っ込む
Bitinfo(3) = 24
'// BitCount 24
Bitinfo(3) = Bitinfo(3) << 16
'// Planes 1
Bitinfo(3) = Bitinfo(3) or 1
'// Compression  BI_RGB = 0
Bitinfo(4) = BI_RGB

'// 作成した情報をポインタへ格納
Dim pBI as IntPtr

'// 領域の確保
pBI = Marshal.AllocHGlobal(40)

'// ポインタへ格納
Marshal.Copy(Bitinfo, 0, pBI, 10)

'// 関数の戻り値
Dim fRet as integer
'// 関数のエラー取得用
Dim fError as integer

'// ImagePtr:画像データの入ったVirtualAllocで確保した領域のポインタ
'// DIB_RGB_COLORS = 0, SRCCOPY = &HCC0020
fRet = StretchDIBits(ImageHDC, 0, 0, 400, 400, 0, 0, 400, 400, ImagePtr, pBI, DIB_RGB_COLORS, SRCCOPY)
fError = GetLastError

PicDraw.Dispose()


何かお気づきの点がありましたら、お手数ではございますがご教授頂けると幸いです。

引用返信 編集キー/
■40412 / inTopicNo.2)  Re[1]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ ふくちゃん (53回)-(2009/08/25(Tue) 12:38:23)
2009/08/25(Tue) 12:41:38 編集(投稿者)

あまりVBの経験がありませんが、
Marshal.Copy の引数の順番なっていますか?

http://msdn.microsoft.com/ja-jp/library/ms146635(VS.80).aspx




Public Shared Sub Copy ( _
source As IntPtr, _
destination As Integer(), _
startIndex As Integer, _
length As Integer _
)


パラメータ
source
コピー元のメモリ ポインタ。

destination
コピー先の配列。

startIndex
Copy を開始する配列内の 0 から始まるインデックス。

length
コピーする配列要素の数。




ちなみに
>>'// ポインタへ格納
でやりたいことってなんなんでしょうか?
引用返信 編集キー/
■40413 / inTopicNo.3)  Re[2]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ AYM (10回)-(2009/08/25(Tue) 12:43:58)
2009/08/25(Tue) 12:47:50 編集(投稿者)
2009/08/25(Tue) 12:46:54 編集(投稿者)

ふくちゃんさん、回答ありがとうございます。
Marshal.Copyはオーバーロードされていて、ご指摘して頂いた引数の場合は、ポインタからローカルの配列へのコピーになるかと思います。
記述したソースでは、ローカル配列からポインタへのコピーを行っており、またメモリの中身を参照したところ、
問題なさそうでした。

>ちなみに
>>>'// ポインタへ格納
>でやりたいことってなんなんでしょうか?
StretchDIBitsの11番目の引数がBITMAPINFO構造体の先頭ポインタを渡す事になっており、VB.NETではIntptrで内容を渡すしかないのかな?
と思い、ポインタへの格納を行っております。

引用返信 編集キー/
■40416 / inTopicNo.4)  Re[3]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ Hongliang (455回)-(2009/08/25(Tue) 15:01:02)
掲載されている範囲では問題なさそうです。同様のコードで動きましたし。
他のところに問題があるのかも知れません。
CreateGraphics 呼び出してるのがどういう意図なのかにもよりますが。

> StretchDIBitsの11番目の引数がBITMAPINFO構造体の先頭ポインタを渡す事になっており、VB.NETではIntptrで内容を渡すしかないのかな?
しかないわけではありませんが、速度を重視するなら IntPtr をフィールドに置いておいて使い回すのがいいでしょう。
逆に、描画のたびに配列からコピーするのなら無駄ですね。第11引数に Integer() を渡せばメモリの解放を考えずに済みます。
引用返信 編集キー/
■40418 / inTopicNo.5)  Re[4]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ ふくちゃん (54回)-(2009/08/25(Tue) 15:14:26)
2009/08/25(Tue) 15:17:52 編集(投稿者)
2009/08/25(Tue) 15:17:11 編集(投稿者)

すいません。 素朴な疑問。
'// ImagePtr:画像データの入ったVirtualAllocで確保した領域のポインタ
って何バイト確保していますか?

'// イメージ横サイズ
Bitinfo(1) = 400
'// イメージ縦サイズ
Bitinfo(2) = 400
'// BitCountとPlanesはWORDの為、ShiftしてDWORDに突っ込む
Bitinfo(3) = 24

ということは、
400×400×3バイト分バッファを確保する必要があると思うのですが、
確保できていますでしょうか?


引用返信 編集キー/
■40419 / inTopicNo.6)  Re[5]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ AYM (11回)-(2009/08/25(Tue) 15:23:53)
Hongliang様
回答ありがとうございます。
>CreateGraphics 呼び出してるのがどういう意図なのかにもよりますが。
こちらにコードを乗せた時は、上記のコードは全てFormLoadイベント内で行って居た為、
PictureBoxのHDCを取得する為に呼び出していました。
現在は、PaintEventにてStretchDIBits関数を呼び出す用に修正した為、CreateGraphicsを呼び出す事はなくなりました。
こちらでは現在、StretchDIBits関数を呼び出すと相変わらず戻り値は0ですが、GetLastErrorの値が
0x3F0→存在しないトークンを参照しようとしました。
と表示されるようになりました。
画像は相変わらず表示されておりません><

ふくちゃん様
Marshal.AllocHGlobalにて確保している領域は画像自体のサイズではなく、StretchDIBits関数に渡すDIBの情報を持った構造体のサイズになります。
BITMAPINFOHEADER構造体のサイズですね。
引用返信 編集キー/
■40421 / inTopicNo.7)  Re[6]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ Hongliang (456回)-(2009/08/25(Tue) 16:16:10)
GDI_ERROR を返さないときに GetLastError しても意味のある値は返さないと思いますよ。

> Marshal.AllocHGlobalにて確保している領域は画像自体のサイズではなく、StretchDIBits関数に渡すDIBの情報を持った構造体のサイズになります。
> BITMAPINFOHEADER構造体のサイズですね。
ふくちゃんさんがお尋ねになっているのは pDI ではなく ImagePtr の方でしょう。つまり VirtualAlloc で確保している領域のサイズ。
あとはちゃんと領域をコミットしてるかとか、アクセス保護がちゃんと指定できてるかとか。
引用返信 編集キー/
■40422 / inTopicNo.8)  Re[7]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ AYM (12回)-(2009/08/25(Tue) 18:03:56)
2009/08/25(Tue) 18:04:59 編集(投稿者)

ふくちゃん様
失礼しました。
画像データの領域確保については問題なくできております。

Hongliang様
ご指摘ありがとうございました。
あの後テストしてみたら、画像が表示されました。
ただ、PictureBoxのHDCの値がうまく取得できないときがあるのか、表示されたりされなかったりします。
テストで取得したHDCの値をラベルに表示すると、画像が表示されるようになりました・・・
ちなみに、実際に表示したいデータは48Bitデータなのですが、48Bit指定はサポートされてないようですね><


引用返信 編集キー/
■40426 / inTopicNo.9)  Re[8]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ ふくちゃん (55回)-(2009/08/25(Tue) 18:50:59)
2009/08/25(Tue) 18:51:25 編集(投稿者)

失礼。
Hongliangさんフォローありがとうございます。

C++っぽいif文で申し訳ないですが、
C++にあるCWndのメソッドの
GetSafeHwnd
ってあります?
安全のために下のようにしてみて、
if文の中に入るかどうかってみてみました?
MFCだけですっけ?GetSafeHwnd?

'// HDCの取得
Dim ImageHDC as IntPtr
//ImageHDC = PicDraw.GetHDC()
ImageHDC = PicDraw.GetSafeHwnd();

if(NULL == ImageHDC) {
return;
}



引用返信 編集キー/
■40526 / inTopicNo.10)  Re[9]: VB.NETでのStretchDIBitsでの画像表示
□投稿者/ AYM (13回)-(2009/08/27(Thu) 13:27:11)
ふくちゃん様

返事が遅くなり申し訳ありません。
一応調べたかぎりではGetSafeHwndはMFCの機能・・・なのか
使えないような感じでした。

現在は、一応画像の描画まではできるようになった為(若干疑問が残る部分もありますが)
遅くなりましたが、解決済みとさせて頂きます。
回答して頂いた、ふくちゃん様・Hongliang様、ありがとうございました。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -