ホワイトシルエット画像を作成する | STUDIO yu- blog

STUDIO yu- blog

備忘録メモ。プランニングや技術関連が中心。

Public Function makeWhiteSilhouette(ByVal tex As Bitmap) As Bitmap
        If tex Is Nothing Then
            Return Nothing
        End If

        Dim _texShadow As New Bitmap(tex.Width, tex.Height)

        Dim f(tex.Width * tex.Height * 4) As Byte
        Dim bmd As Imaging.BitmapData
        bmd = tex.LockBits(New Rectangle(0, 0, tex.Width, tex.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
        System.Runtime.InteropServices.Marshal.Copy(bmd.Scan0, f, 0, f.Length - 1)
        tex.UnlockBits(bmd)

        For i = 0 To f.Length / 4 - 1
            If f(i * 4 + 3) <> 0 Then
                f(i * 4 + 0) = 255
                f(i * 4 + 1) = 255
                f(i * 4 + 2) = 255
            Else
                f(i * 4 + 0) = 0
                f(i * 4 + 1) = 0
                f(i * 4 + 2) = 0
                f(i * 4 + 3) = 0
            End If
        Next
        Dim bmdShadow As Imaging.BitmapData
        bmdShadow = _texShadow.LockBits(New Rectangle(0, 0, _texShadow.Width, _texShadow.Height), Imaging.ImageLockMode.WriteOnly, Imaging.PixelFormat.Format32bppArgb)
        System.Runtime.InteropServices.Marshal.Copy(f, 0, bmdShadow.Scan0, f.Length - 1)
        _texShadow.UnlockBits(bmdShadow)

Return _texShadow

End Function

--------------------------------------------------------

画像の自由な色変更を行う際、読み込んだ色情報だけでなく、
真っ白なシルエットがほしいときがあります。
BitmapDataを用いて、それなりに高速にホワイトシルエット画像を生成するコードです。

BitmapをLockBitsしてメモリアドレスを(仮想的に)固定して、
そこの(疑似)ポインタを取得してMemCopy的なことをしています。
UnlockBitsを忘れずに。

ちなみに、アルファ成分はそのままにしておきたいので、
RGBA8888の4番目(A部分)の値には手を入れていません。

■処理の流れ
1. 出力用のビットマップを用意
2. バイト配列(32bit * 総ピクセル数)を用意
3. 元画像をメモリにアロケート(固定)
4. Marshal.Copyでバイト配列に画素データを一括コピー
5. バイト配列を画素データとしてごにょごにょしてやる
6. 出力用のビットマップをアロケート
7. バイト配列をMarshal.Copyして画素データに上書き
8. 完成!

バイト配列の*4は、画素データが32bit = 4Byteなので*4しています。
シルエットに限らず、画像処理をそれなりに高速に行う場合には
GetPixel/SetPixelではなく、BitmapDataを経由するのがオススメです。