Microsoft .NET Framework API でのsetDIBitsはなんですか?

タグの編集
投稿者 YAYA  (社会人) 投稿日時 2009/11/10 07:34:26
いつもお世話になっています。データを画像に変換すときvbではsetDIBitsを使用していたのですが、 .NET Frameworkでは、何が対応するのでしょうか?わかる方いらしたら教えてください。SetPixelは速度が遅いので困っています。
投稿者 るきお  (社会人) 投稿日時 2009/11/10 08:01:32
こんにちは。

Bitmap.UnlockBitsでしょうか。

MSDNライブラリに載っているサンプルですが参考になりますか?
Private Sub Form1_Paint(ByVal sender As ObjectByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Me.LockUnlockBitsExample(e)
    End Sub
    Private Sub LockUnlockBitsExample(ByVal e As PaintEventArgs)

        ' Create a new bitmap. 
        Dim bmp As New Bitmap("C:\test\test.jpg")

        ' Lock the bitmap's bits.   
        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, _
            Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)

        ' Get the address of the first line. 
        Dim ptr As IntPtr = bmpData.Scan0

        ' Declare an array to hold the bytes of the bitmap. 
        ' This code is specific to a bitmap with 24 bits per pixels. 
        Dim bytes As Integer = bmpData.Stride * bmp.Height
        Dim rgbValues(bytes - 1) As Byte

        ' Copy the RGB values into the array. 
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)

        ' Set every third value to 255. A 24bpp image will look red. 
        For counter As Integer = 2 To rgbValues.Length - 1 Step 3
            rgbValues(counter) = 255
        Next

        ' Copy the RGB values back to the bitmap 
        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes)

        ' Unlock the bits. 
        bmp.UnlockBits(bmpData)

        ' Draw the modified image. 
        e.Graphics.DrawImage(bmp, 0, 150)

    End Sub
投稿者 cupid  (社会人) 投稿日時 2009/11/10 08:09:40
「setDIBits」は知りませんが、「SetPixel」のような事をBitmapテーブル使って
しようとすると、いくらか面倒です。残念ながら、それに対応した機能は無いでしょう。

画像からBitmapデータ取得して何かする場合、下記の例を理解する必要があるでしょう。
http://msdn.microsoft.com/ja-jp/library/5ey6h79d.aspx

VB2008Helpにも同じ説明は出ています。キーワードは「Bitmap.LockBitsメソッド」
かなり周辺の事も理解する必要があるので、一朝一夕には行かないかもしれません。
投稿者 cupid  (社会人) 投稿日時 2009/11/10 08:11:46
あら、同じ内容が重複しちゃいましたね。
投稿者 YAYA  (社会人) 投稿日時 2009/11/10 08:27:08
るきお様、cupid様 ご返答ありがとうございます。Copy the RGB values into the array. 
を行わないで直接 Copy the RGB values back to the bitmap に行うことができました。
処理速度を向上することができました。ありがとうございました。
投稿者 るきお  (社会人) 投稿日時 2009/11/10 08:38:32
>処理速度を向上することができました。ありがとうございました。 
具体的にはどうやったんですか?

cupidさんや私が挙げたサンプルと同じ手法ですか?
それとも違ういいやり方がありましたか?
投稿者 YAYA  (社会人) 投稿日時 2009/11/11 06:16:07
遅くなってごめんなさい。
同じだと思います。恥ずかしいはなし、LockBitsを勘違いしていて、あらかじめデータを
用意してあるのに、
①画像用データ作成 (配列)
②bmp準備 ここからサンプル
③LockBits
④bmpのメモリーから配列にコピー?
⑤配列を加工  あらかじめのデータを挿入
⑥配列からメモリーへ?
⑦UnlockBits
⑧描写
してしまっていました。
①画像用データ作成 (配列)
②bmp準備 ここからサンプル
③LockBits
④メモリーから配列にコピー? ********ここは行わない
⑤あらかじめのデータを挿入
⑥配列からメモリーへ?
⑦UnlockBits
⑧描写
でいいのだとこの前の返答で気づくことができました。
ありがとうございました。1000回の描写で7割ぐらいの速度でした。(環境で変化?)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/11/11 06:59:46
> 1000回の描写で7割ぐらいの速度でした。(環境で変化?)

もし、さらに速度を稼ぐ必要がある場合には、LockBits の部分だけでも、
VB ではなく C# を用いて、ポインタ操作するという手もあります。
(残念ながら VB では、ポインタを直接扱う事ができません)

C# の unsafe を使って直接ポインタを操作するようにすると、
Marshal.Copy で転記しながら制御するよりも数倍以上早くなる可能性があります。

http://homepage2.nifty.com/nonnon/SoftSample/CS.NET/SampleBitmapPlus.html
http://dobon.net/vb/bbs/log3-14/8362.html
投稿者 YAYA  (社会人) 投稿日時 2009/11/11 07:49:15
魔界の仮面弁士様 ありがとうございます。
C#ですか~ むずかしそうですね~
投稿者 (削除されました)  () 投稿日時 2009/11/11 08:58:57
(削除されました)
投稿者 YAYA  (社会人) 投稿日時 2009/11/11 09:44:36
魔界の仮面弁士様 ありがとうございます。
C#  unsafe LockBits 確認できました。C#方がやっぱり早い結果でした。

ついかで
VB.NETあらかじめデータを用意しBMPにデータを挿入する場合、Imaging.ImageLockMode.WriteOnlyで速度UPできました。
C#でも行ってみます。
るきお様、cupid様
ありがとうございました。
ただ、APIの方が倍?はやかったため、APIが使用できる環境であればまだまだAPIは
やめられないかもです。