VB2005を使用しています。
カメラから画像Dataを取得し、API関数で
モノクロで画像を表示させようとしています。
Dim memDC As Integer
Dim hDIBSection As Integer
Dim hOldBmp As Integer
Dim lpDIB As Integer
'まずはメモリDCを作る
memDC = CreateCompatibleDC(hdc)
'DIBSectionを作る
hDIBSection = CreateDIBSection(memDC, bmpInfo, DIB_RGB_COLORS, lpDIB, 0, 0)
ここで、”保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。”
と言うエラーが出てしまって苦戦しています。
どなたか、御教授頂けますでしょうか。
よろしくお願いします。
memDC、hDIBSection、hOldBmp、lpDIB はすべてポインタかハンドルですので、IntPtr にすべきです。
あとは、各引数が間違えていないことを確認するくらいしか、提示されたコードで言えることはありません。
lpDIB あたりが怪しそうではありますが。
aetos様返答ありがとうございます。
memDC、hDIBSection、hOldBmp、lpDIB をIntPtr にしました。
仮にlpDIB=0 として見ましたが、やはりエラーとなります。
コードの詳細を記載させて頂きます。
間違えている所がありましたら、皆様御指摘よろしくお願いします。
’API宣言
Public Declare Function SetDIBColorTable Lib "gdi32" (ByVal hdc As IntPtr, ByVal uStartIndex As Integer, ByVal cEntries As Integer, ByVal pColors As RGBQUAD) As Integer
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As IntPtr) As Integer
Public Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As IntPtr, ByVal pBitmapInfo As BITMAPINFOHEADER, ByVal un As Integer, ByVal lplpVoid As Integer, ByVal handle As Integer, ByVal dw As Integer) As Integer
Public Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
Public Declare Function StretchDIBits Lib "GDI32" (ByVal hDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal dx As Integer, ByVal dy As Integer, ByVal SrcX As Integer, ByVal SrcY As Integer, ByVal wSrcWidth As Integer, ByVal wSrcHeight As Integer, ByRef lpBits As Byte, ByRef lpBitsInfo As BITMAPINFOHEADER, ByVal wUsage As Integer, ByVal dwRop As Integer) As Integer
Public Const SRCCOPY As Integer = &HCC0020
Dim bmpInfo As BITMAPINFOHEADER
Dim bmiColors(255) As RGBQUAD ' DIBカラー設定格納
Dim memDC As IntPtr
Dim hDIBSection As IntPtr
Dim hOldBmp As IntPtr
Dim lpDIB As IntPtr
Dim hdc As IntPtr
Dim PixelData(76800) As Byte
'BITMAPINFOHEADER
bmpInfo.biBitCount = 8 ' カメラからの出力が8bitなので8を設定
bmpInfo.biClrImportant = 0
bmpInfo.biClrUsed = 0
bmpInfo.biCompression = 0
bmpInfo.biHeight = 240
bmpInfo.biPlanes = 1
bmpInfo.biSize = 40 ' SizeOf(BITMAPINFOHEADER)
bmpInfo.biSizeImage = 76800
bmpInfo.biWidth = 320
bmpInfo.biXPelsPerMeter = 0
bmpInfo.biYPelsPerMeter = 0
For i = 0 To 255
bmiColors(i).rgbBlue = i
bmiColors(i).rgbGreen = i
bmiColors(i).rgbRed = i
bmiColors(i).rgbReserved = 0
Next i
' デバイスコンテキストハンドル取得
hdc = Form1.Picture1.CreateGraphics.GetHdc
'まずはメモリDCを作る
memDC = CreateCompatibleDC(hdc)
'DIBSectionを作る
hDIBSection = CreateDIBSection(memDC, bmpInfo, DIB_RGB_COLORS, lpDIB, 0, 0)
'DIBSectionとhMemDCを関連付ける
hOldBmp = SelectObject(memDC, hDIBSection)
'カラーパレットを変更する
SetDIBColorTable(memDC, 0, 255, bmiColors(0))
'画像を表示する
StretchDIBits(hdc, 0, 0, 320, 240, 0, 0, 320, 240, PixelData(0), bmpInfo, DIB_RGB_COLORS, SRCCOPY)
よろしくお願いします。
って言うか、カメラからはどうやって画像データを取得するんでしょうか。
編集 削除画像Dataの取得は、
カメラに付属の関数を用いて
画像Dataを取得しています。
PixelData(76800)の配列の中にDataは
格納されています。dim宣言の後に取得しています。
そのカメラ付属の関数の宣言を載せてください。
編集 削除申し訳ありません。
カメラ付属の関数の宣言を載せることが出来ません。
イメージとしては、320×240の画像を1枚取得します。(Dataは8bitです)
そのDataをStretchDIBits関数で表示します。
その関数は、引数に BYTE* を取り、アプリ側で確保したバッファを渡して呼び出すようなものですか?
要は、そのためのポインタが取得できればよいわけで、それなら、CreateDIBSection など使うより楽な方法があるのではないでしょうか。
例えば、Bitmap オブジェクトを作り、その LockBits メソッドを呼ぶと、ビットバッファへのポインタが手に入ります。
これをカメラの関数に渡すのはどうでしょう。
第4引数は、 ByVal ではなく、 ByRef です。
編集 削除>第4引数は、 ByVal ではなく、 ByRef です。
御指摘ありがとうございます。
修正してみましたが、やはりエラーとなってしまいます。
>例えば、Bitmap オブジェクトを作り、その LockBits メソッドを呼ぶと、ビットバッファへのポインタが手に入ります。
この方法を試してみたいと思います。
上記方法以外に、PixelData(76800)の画素Dataを
PictuerBOXに表示する一番簡単な方法はありますでしょうか?
「画像データ」の中身次第ですが、Bitmap(Integer, Integer, Integer, PixelFormat, IntPtr) コンストラクタを使って Bitmap オブジェクトを生成するとか。
編集 削除StretchDIBits で描画するんだったら、作成したメモリDC や DIBSection
は一切使われていないので全く意味がありませんね。
BITMAPINFOHEADER の後にパレットのデータがメモリが連続して配置されていれば
配列の内容を書き換えるだけで適用されます。
Bitmap オブジェクトで作る方が楽なので aetos さんか Hongliang さんの方法を
おすすめします。
#ちなみに StretchDIBits は重いです。
皆様、返信ありがとうございます。
Bitmap オブジェクトだとやはり時間がかかってしまいます…。
>StretchDIBits で描画するんだったら、作成したメモリDC や DIBSection
>は一切使われていないので全く意味がありませんね。
>BITMAPINFOHEADER の後にパレットのデータがメモリが連続して配置されていれば
>配列の内容を書き換えるだけで適用されます。
上記内容をもう少し具体的に教えて頂けないでしょうか?
出来れば、コード等のアドバイスもよろしくお願いします。
>Bitmap オブジェクトだとやはり時間がかかってしまいます…。
具体的にどの部分で時間がかかりますか?
最初に8ビットの Bitmap オブジェクトが構築できたら
描画用に32ビットに変換して、そちらを使った方がいいと思います。
>上記内容をもう少し具体的に教えて頂けないでしょうか?
>出来れば、コード等のアドバイスもよろしくお願いします。
まず、DIB でも DIBSection でも8ビット以下のビットマップの場合は
BITMAPINFOHEADER と RGBQUAD のメモリが連続していることが
重要なので、bmpInfo 変数を無理矢理渡しているのはまずい気がします。
RGBQUAD を256個持つ BITMAPINFO 構造体を定義した方がいいのではないでしょうか。
DIBSection を使う場合は作成後に、選択しているメモリDCに対して
SetDIBitsToDevice で画素を転送しておきます。
ウインドウへの描画には StretchBlt や BitBlt を使用します。
#APIの宣言についてはまだ見直す必要がありそうです。
第2引数も、 ByVal ではなく ByRef です。
編集 削除皆様、お陰様で画像を出す事が出来ました。
本当に助かりました!
ありがとうございました!