16色Bitmapを作成し描画する(LockBits使用)


事前準備

・フォームにテキストボックスとボタンを貼り付ける

・その下にPictureBoxを貼り付ける

・PictureBoxのBackColorプロパティをWhiteにする


テキストボックスの中に数字を1~15を入れ、
ボタンをクリックすることで、カラーパレットの
インデックスをセットします。
その後、マウスドラッグで描画します。


【ソースコード】


Imports System.Drawing.Imaging

Public Class Form1

 Private Col(15) As Color
 Private Palette As ColorPalette
 Private ind As Integer = 0
 Private mDownFlg As Boolean = False
 Private stX As Integer, stY As Integer
 Private enX As Integer, enY As Integer

 Private Sub MakeColorPalette()
  Col(0) = Color.Transparent
  Col(1) = Color.Red
  Col(2) = Color.Blue
  Col(3) = Color.Green
  Col(4) = Color.Yellow
  Col(5) = Color.Aqua
  Col(6) = Color.Purple
  Col(7) = Color.Olive
  Col(8) = Color.Pink
  Col(9) = Color.Silver
  Col(10) = Color.Gold
  Col(11) = Color.SkyBlue
  Col(12) = Color.Tomato
  Col(13) = Color.Violet
  Col(14) = Color.White
  Col(15) = Color.Black
 End Sub

 Private bmp As Bitmap

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

  MakeColorPalette()
  bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height, PixelFormat.Format4bppIndexed)
  Palette = bmp.Palette

  For i As Integer = 0 To 15
   Palette.Entries(i) = Col(i)
  Next
  bmp.Palette = Palette

 End Sub

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

  Integer.TryParse(TextBox1.Text, ind)

 End Sub

 Private Sub mDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseDown

  mDownFlg = True
  stX = e.X : stY = e.Y
  enX = e.X : enY = e.Y

 End Sub

 Private Sub mMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseMove

  If mDownFlg = False Then Exit Sub

  enX = e.X : enY = e.Y
  Dim bmpDt As BitmapData = bmp.LockBits(New Rectangle(0, 0, PictureBox1.Width, PictureBox1.Height), ImageLockMode.ReadWrite, PixelFormat.Format4bppIndexed)
  Dim ptr As IntPtr = bmpDt.Scan0
  Dim bytes As Integer = bmpDt.Stride * PictureBox1.Height
  Console.WriteLine(bmpDt.Stride)
  Dim rgbvalues(bytes) As Byte
  System.Runtime.InteropServices.Marshal.Copy(ptr, rgbvalues, 0, bytes)

  For i As Integer = Math.Min(stX, enX) To Math.Max(stX, enX)
   For j As Integer = Math.Min(stY, enY) To Math.Min(stY, enY)
    rgbvalues(CInt(i * bmpDt.Stride / PictureBox1.Width + j * bmpDt.Stride)) = CByte(ind)
   Next
  Next

  System.Runtime.InteropServices.Marshal.Copy(rgbvalues, 0, ptr, bytes)
  bmp.UnlockBits(bmpDt)
  Dim g As Graphics
  g = Graphics.FromHwnd(PictureBox1.Handle)
  g.DrawImage(bmp, 0, 0)
  g.Dispose()
  stX = e.X : stY = e.Y

 End Sub

 Private Sub mUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseUp
  mDownFlg = False
  Dim g As Graphics = Graphics.FromHwnd(PictureBox1.Handle)
  g.DrawImage(bmp, 0, 0)
  g.Dispose()
 End Sub

End Class



テキストボックスに0を入れると、透過色での描画になります。
4bppIndexedのBitmapですので、カラーパレットを作成し、
そのインデックスを、各ピクセルに割り当てていくことになります。

ここでは、テキストボックス内の数字が、カラーパレットの
インデックスになります。(ボタンをクリックする必要がありますが)

ただし、Graphics.Drawシリーズが使えないなど、
不便極まりないため、32bppArgb形式のBitmapなどを作成し、
それを8bpp(256色)や4bpp(16色)に変換した方が楽かもしれません。


関連記事



・Bitmap.LockBitsメソッド

・Byte配列

・Image.Palette

・画像を読み込み編集する1(LockBits)


システム開発のためのVB.NETプログラミング関係一覧に戻る


Google検索の結果