酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windows MobileでBitmapの生データにアクセスする

.NET Compact Frameworkは、.NET Frameworkからモバイル向けにいくつか機能を削除されています。Graphics.DrawImage(Image, PointF[])が削除されており、線対称の反転処理や回転処理を自作する必要があります。

今回は、それらの処理の紹介の前に、直接Bitmapオブジェクトの生データにアクセスする処理をご紹介します。

最初に、buttonとpictureBoxコントロールを適当な位置に貼り付けておいてください。

Bitmapの生データにアクセスする

VB.NET

  ' 以下の名前空間を指定しておいてください
  ' Imports System.Drawing
  ' Imports System.Drawing.Imaging
  ' Imports System.Runtime.InteropServices
    
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
      
    Dim filePath As String = "\Storage Card\miku kirintamura.jpg"
    Dim srcBmp As New Bitmap(filePath)
    
    ' 直接データを触る矩形を指定する
    Dim lockRect As New Rectangle(0, 0, srcBmp.Width, srcBmp.Height)
    
    ' Bitmapをシステムメモリにロックする
    Dim bmpData As BitmapData = srcBmp.LockBits(lockRect, _
                                             ImageLockMode.ReadWrite, _
                                             PixelFormat.Format32bppRgb)
    
    ' 画像データのコピー先の領域を確保する
    Dim pixSize As Integer = 4
    Dim lineSize As Integer = srcBmp.Width * pixSize
    Dim dataSize As Integer = srcBmp.Height * lineSize
    Dim data(dataSize - 1) As Byte
    
    ' 元画像バッファから加工用バッファへコピーを行う。
    Marshal.Copy(bmpData.Scan0, data, 0, data.Length)
    
    ' 読み出した画像の中心部分をマゼンタにする
    Dim startIndex As Integer = dataSize / 2
    Dim endIndex As Integer = startIndex + (lineSize * 220)
    For i As Integer = startIndex To endIndex Step pixSize
      ' B
      data(i) = 255
      ' G
      data(i + 1) = 0
      ' R
      data(i + 2) = 255
      ' A
      data(i + 3) = 255
    Next i
    
    ' 加工用バッファから元画像バッファへコピーを行う。
    Marshal.Copy(data, 0, bmpData.Scan0, data.Length)
    
    ' システムメモリからBitmapのロックを解除する
    srcBmp.UnlockBits(bmpData)
    
    ' Graphicsオブジェクトを利用して描画を行う
    Dim bmp As New Bitmap(srcBmp.Width, srcBmp.Height)
    Using g As Graphics = Graphics.FromImage(bmp)
      g.DrawImage(srcBmp, 0, 0)
    End Using
    
    ' PictureBoxへ表示
    Me.PictureBox1.Image = bmp
  End Sub

C#

  // 以下の名前空間を指定しておいてください
  // Using System.Drawing;
  // Using System.Drawing.Imaging;
  // Using System.Runtime.InteropServices;
  
  private void Button1_Click(System.Object sender, System.EventArgs e)
  {
    string filePath = "\\Storage Card\\miku kirintamura.jpg";
    Bitmap srcBmp = new Bitmap(filePath);
    
    // 直接データを触る矩形を指定する
    Rectangle lockRect = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
    
    // Bitmapをシステムメモリにロックする
    BitmapData bmpData = srcBmp.LockBits(lockRect, 
                                         ImageLockMode.ReadWrite, 
                                         PixelFormat.Format32bppRgb);
    
    // 画像データのコピー先の領域を確保する
    int pixSize = 4;
    int lineSize = srcBmp.Width * pixSize;
    int dataSize = srcBmp.Height * lineSize;
    byte[] data = new byte[dataSize];
    
    // 元画像バッファから加工用バッファへコピーを行う。
    Marshal.Copy(bmpData.Scan0, data, 0, data.Length);
    
    // 読み出した画像の中心部分をマゼンタにする
    int startIndex = dataSize / 2;
    int endIndex = startIndex + (lineSize * 220);
    for (int i = startIndex; i <= endIndex; i += pixSize) {
      // B
      data(i) = 255;
      // G
      data(i + 1) = 0;
      // R
      data(i + 2) = 255;
      // A
      data(i + 3) = 255;
    }
    
    // 加工用バッファから元画像バッファへコピーを行う。
    Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
    
    // システムメモリからBitmapのロックを解除する
    srcBmp.UnlockBits(bmpData);
    
    // Graphicsオブジェクトを利用して描画を行う
    Bitmap bmp = new Bitmap(srcBmp.Width, srcBmp.Height);
    using (Graphics g = Graphics.FromImage(bmp)) {
      g.DrawImage(srcBmp, 0, 0);
    }
    
    // PictureBoxへ表示
    this.PictureBox1.Image = bmp;
  }

上記のコードを実行すると、エミュレータでの結果のように読み出した画像の中心部分をマゼンタで塗りつぶされています。

実行結果

f:id:ch3cooh393:20141108201803p:plain

関連記事

Windows Mobile(.NET Compact Framework)を使ってアプリ開発する際に逆引きとしてお使いください。