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.aspx | Bitmap.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で定義した関数を呼び出すように変えて、その中で書き換えてやればよさげ。
今日はとりあえずここまで。