VB.net で GetDIBits を使用するには?

解決


三郎太  2004-02-18 15:14:37  No: 82100  IP: [192.*.*.*]

こんにちは、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

原因がつかめていないため、
非常に長くなってしまいました、申し訳ないです。
どうか、救いの手をよろしくお願いします。

編集    削除
魔界の仮面弁士  2004-02-18 20:41:56  No: 82101  IP: [192.*.*.*]

> 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 で読み取るとか。

編集    削除
三郎太  2004-02-18 21:59:04  No: 82102  IP: [192.*.*.*]

おおおぉ!?
出来る!  凄い、このようなすばらしい方法があったとは。
素早い対応ありがとうございました、助かりました。
おかげで、やっと次の作業に進めそうです。

もう少し勉強して、なんとか一通りの事が分かりましたら
ここにフィードバックさせて頂こうと思います。

魔界の仮面弁士さん、本当にありがとうございました。

編集    削除