flat7th

C++とC#のBitmap転送

created 2011-12-11 modified 2011-12-11 

調査メモ。

C++側のdllに BITMAPINFO と 画像データ(幅x高さx(32bit/pixel))があって、そのデータを使って C#側の PictureBox をガボッと更新したい。

C#側で画像の矩形領域を表示するフォーム部品は PictureBox。

PictureBox には image というメンバがあって、これが全ピクセルの画像データを握ってる。

例えばbmpファイルを読んで、その内容でPictureBoxを更新するような場合、imageメンバ に Bitmap を代入してやると、一気に書き換えできるっぽい。

Imageが抽象型でBitmapが具体型。

System.Drawing.Image
 △
 |_ Bitmap
 |_ Metafile




やりたいのは全ビットを30FPSとかで更新すること。

SetPixelとか言う、1ピクセルずつ色を代入するメソッドがあるんだが、これで 1024x768 をXYでループしてたら、とんでもない関数コール回数になってしまう。それを毎秒30フレームとかだとすごいことに...。

一度に大量のピクセルを更新するときは Bitmap::LockBits() メソッドを使うみたい。

リンクメモ
http://msdn.microsoft.com/ja-jp/library/5ey6h79d.aspxBitmap.LockBitsメソッド

リンク切れすると困るので、ちょっとコピペしておこう...

   private void LockUnlockBitsExample(PaintEventArgs e)
       {

           // Create a new bitmap.
           Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");

           // Lock the bitmap's bits.  //kkk:ロック
           Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
           System.Drawing.Imaging.BitmapData bmpData =
               bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
               bmp.PixelFormat);

           // Get the address of the first line. //kkk:ピクセルデータの先頭アドレス 
           IntPtr ptr = bmpData.Scan0;

    //ここから
           // Declare an array to hold the bytes of the bitmap. //kkk:作業バッファ確保
           int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;
           byte[] rgbValues = new byte[bytes];

           // Copy the RGB values into the array. //kkk:作業バッファへ一括コピー
           System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

           // Set every third value to 255. A 24bpp bitmap will look red. 
           //kkk:作業バッファ上で赤いじる。このサンプルは24bit/pixelだね
           for (int counter = 2; counter < rgbValues.Length; counter += 3)
               rgbValues[counter] = 255;

           // Copy the RGB values back to the bitmap //kkk:作業バッファからビットマップへ書き戻す
           System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
    //ここまでをいじればよさげ

           // Unlock the bits. //kkk:アンロック
           bmp.UnlockBits(bmpData);

           // Draw the modified image. //kkk:更新したイメージを描画
           e.Graphics.DrawImage(bmp, 0, 150);

       }

上記の、ここから ここまで のところを、C++側のdllで定義した関数を呼び出すように変えて、その中で書き換えてやればよさげ。

今日はとりあえずここまで。