こんにちは、VB.netでwin32APIの利用に関する質問です。
ピクチャボックスに読みこんだビットマップの
全ピクセルのRGBをメモリに取りこみたいのですが、
GetPixelメソッドを使用すると尋常でない時間がかかってます。
VB6.0ではウェブ上のサンプルを参考にさせてもらい、
なんとかGetDIBitsを利用出来たのですが、
VB.netに移行しようとしてつまずいています。
デバイスコンテキスト取得の為に、GetDCを使用する、
という所までは分かったつもりなのですが、
上手くメモリに格納出来ません。 と申しますか、
GetDIBitsの返り値が0でエラーとの事でした。
OSはXP、Frameworkは1.0のままです。
どうかご教授願います。
長くて申し訳ないのですが、コードを載せさせていただきます。
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Integer, ByVal hBitmap As Integer, ByVal nStartScan As Integer, ByVal nNumScans As Integer, ByRef lpBits As Integer, ByRef lpBI As Object, ByVal wUsage As Integer) As Integer
あとGetDC,SelectObject,DeleteObjectを宣言しています
Friend Structure BITMAPINFOHEADER
...
End Structure
Friend Structure RGBQUAD
...
End Structure
Friend Structure BITMAPINFO
Friend bmiHeader As BITMAPINFOHEADER
Friend bmiColors() As RGBQUAD
End Structure
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
Dim bmpinfo As BITMAPINFO
Dim hDC As Integer
Dim hbm As Integer
Dim ohbm As Integer
Dim Pixel(,) As Integer
ReDim bmpinfo.bmiColors(255)
With bmpinfo.bmiHeader
.biSize = 40
(一応40は値としては合ってはいると思います、
Len(bmpinfo.bmiHeader)とするとエラーが出ました)
.biWidth = PictureBox1.Width
.biHeight = PictureBox1.Height
.biPlanes = 1
.biBitCount = 32
.biCompression = 0
.biSizeImage = PictureBox1.Width * PictureBox1.Height * 4
.biClrUsed = 0
End With
hDC = GetDC(PictureBox1.Handle.ToInt32)
hbm = CreateCompatibleBitmap(hDC, PictureBox1.Width, PictureBox1.Height)
ohbm = SelectObject(hDC, hbm)
ReDim Pixel(PictureBox1.Width - 1, PictureBox1.Height - 1)
GetDIBits(hDC, ohbm, 0, PictureBox1.Height, Pixel(0, 0), bmpinfo, 0)
セレクトで戻して、デリートしてます。
End Sub
原因がつかめていないため、
非常に長くなってしまいました、申し訳ないです。
どうか、救いの手をよろしくお願いします。
> GetPixelメソッドを使用すると尋常でない時間がかかってます。
1点ずつ取得するのではなく、
Dim Bmp As System.Drawing.Bitmap
Bmp = DirectCast(PictureBox1.Image, System.Drawing.Bitmap)
Dim Data As System.Drawing.Imaging.BitmapData
Data = Bmp.LockBits( _
New System.Drawing.Rectangle(0, 0, Bmp.Width, Bmp.Height), _
System.Drawing.Imaging.ImageLockMode.ReadWrite, _
Bmp.PixelFormat)
などとして、 Data.scan0 からのデータを System.Runtime.InteropServices.Marshal で読み取るとか。
おおおぉ!?
出来る! 凄い、このようなすばらしい方法があったとは。
素早い対応ありがとうございました、助かりました。
おかげで、やっと次の作業に進めそうです。
もう少し勉強して、なんとか一通りの事が分かりましたら
ここにフィードバックさせて頂こうと思います。
魔界の仮面弁士さん、本当にありがとうございました。