注意:画像の表示方法が分からないという方は、まず「コントロールやフォームに画像を表示する」をご覧ください。
ネガティブイメージ(色を反転させた画像)を作成するには、画像のすべてのピクセルで、255からRGBの各成分を引きます。この処理は、ColorMatrixクラスを使用すれば簡単にできます。ColorMatrixに関して詳しくは「画像のカラーバランスを補正して表示する」をご覧ください。
以下の例では、指定された画像からネガティブイメージを作成するメソッドを作成しています。また、PictureBoxコントロール(PictureBox1)をクリックすると、画像ファイル(C:\test\1.bmp)のネガティブイメージが表示されるようにしています。
'Imports System.Drawing ''' <summary> ''' 指定された画像からネガティブイメージを作成する ''' </summary> ''' <param name="img">基の画像</param> ''' <returns>作成されたネガティブイメージ</returns> Public Shared Function CreateNegativeImage(ByVal img As Image) As Image 'ネガティブイメージの描画先となるImageオブジェクトを作成 Dim negaImg As New Bitmap(img.Width, img.Height) 'negaImgのGraphicsオブジェクトを取得 Dim g As Graphics = Graphics.FromImage(negaImg) 'ColorMatrixオブジェクトの作成 Dim cm As New System.Drawing.Imaging.ColorMatrix() 'ColorMatrixの行列の値を変更して、色が反転されるようにする cm.Matrix00 = -1 cm.Matrix11 = -1 cm.Matrix22 = -1 cm.Matrix33 = 1 cm.Matrix40 = 1 cm.Matrix41 = 1 cm.Matrix42 = 1 cm.Matrix44 = 1 'ImageAttributesオブジェクトの作成 Dim ia As New System.Drawing.Imaging.ImageAttributes() 'ColorMatrixを設定する ia.SetColorMatrix(cm) 'ImageAttributesを使用して色が反転した画像を描画 g.DrawImage(img, _ New Rectangle(0, 0, img.Width, img.Height), _ 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia) 'リソースを解放する g.Dispose() Return negaImg End Function 'PictureBox1のClickイベントハンドラ Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles PictureBox1.Click 'ネガティブイメージにする画像 Dim img As Image = Image.FromFile("C:\test\1.bmp") 'ネガティブイメージを作成 Dim negaImg As Image = CreateNegativeImage(img) img.Dispose() 'PictureBox1に表示 If PictureBox1.Image IsNot Nothing Then PictureBox1.Image.Dispose() End If PictureBox1.Image = negaImg End Sub
//using System.Drawing; /// <summary> /// 指定された画像からネガティブイメージを作成する /// </summary> /// <param name="img">基の画像</param> /// <returns>作成されたネガティブイメージ</returns> public static Image CreateNegativeImage(Image img) { //ネガティブイメージの描画先となるImageオブジェクトを作成 Bitmap negaImg = new Bitmap(img.Width, img.Height); //negaImgのGraphicsオブジェクトを取得 Graphics g = Graphics.FromImage(negaImg); //ColorMatrixオブジェクトの作成 System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(); //ColorMatrixの行列の値を変更して、色が反転されるようにする cm.Matrix00 = -1; cm.Matrix11 = -1; cm.Matrix22 = -1; cm.Matrix33 = 1; cm.Matrix40 = cm.Matrix41 = cm.Matrix42 = cm.Matrix44 = 1; //ImageAttributesオブジェクトの作成 System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes(); //ColorMatrixを設定する ia.SetColorMatrix(cm); //ImageAttributesを使用して色が反転した画像を描画 g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia); //リソースを解放する g.Dispose(); return negaImg; } //PictureBox1のClickイベントハンドラ private void PictureBox1_Click(object sender, EventArgs e) { //ネガティブイメージにする画像 Image img = Image.FromFile(@"C:\test\1.bmp"); //ネガティブイメージを作成 Image negaImg = CreateNegativeImage(img); img.Dispose(); //PictureBox1に表示 if (PictureBox1.Image != null) { PictureBox1.Image.Dispose(); } PictureBox1.Image = negaImg; }
次にすべてのピクセルデータの色を計算して設定する方法を紹介します。それには、Bitmap.GetPixelメソッドで色を取得して、Bitmap.SetPixelメソッドで色を設定するというやり方が考えられます。しかしこの方法はパフォーマンスに劣るため、大量のピクセルの色を変更する場合は、Bitmap.LockBitsメソッドを使った方がいいです。
この方法によって、指定した画像をネガティブイメージに変更するメソッドの例を示します。
'Imports System.Drawing 'Imports System.Drawing.Imaging ''' <summary> ''' 指定された画像をネガティブイメージに変換する ''' </summary> ''' <param name="img">変換する画像</param> Public Shared Sub ChangeToNegativeImage(ByVal img As Bitmap) '1ピクセルあたりのバイト数を取得する Dim pixelFormat As PixelFormat = img.PixelFormat Dim pixelSize As Integer = Image.GetPixelFormatSize(pixelFormat) / 8 If pixelSize < 3 OrElse 4 < pixelSize Then Throw New ArgumentException( _ "1ピクセルあたり24または32ビットの形式のイメージのみ有効です。", _ "img") End If 'または次のように元の画像とは異なるPixelFormatでLockBitsすることも可能 'この場合、UnlockBitsで元のPixelFormatに戻る 'ただし、元のPixelFormatとLockBits時のPixelFormatが異なる場合は、 '変更した色とは異なる色になる可能性がある 'pixelFormat = PixelFormat.Format32bppArgb 'pixelSize = 4 'Bitmapをロックする Dim bmpData As BitmapData = _ img.LockBits(New Rectangle(0, 0, img.Width, img.Height), _ ImageLockMode.ReadWrite, pixelFormat) If bmpData.Stride < 0 Then img.UnlockBits(bmpData) Throw New ArgumentException( _ "ボトムアップ形式のイメージには対応していません。", _ "img") End If 'ピクセルデータをバイト型配列で取得する Dim ptr As IntPtr = bmpData.Scan0 Dim pixels As Byte() = New Byte(bmpData.Stride * img.Height - 1) {} System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, pixels.Length) 'すべてのピクセルの色を反転させる For y As Integer = 0 To bmpData.Height - 1 For x As Integer = 0 To bmpData.Width - 1 'ピクセルデータでのピクセル(x,y)の開始位置を計算する Dim pos As Integer = y * bmpData.Stride + x * pixelSize '青、緑、赤の色を変更する pixels(pos) = CByte(255 - pixels(pos)) pixels(pos + 1) = CByte(255 - pixels(pos + 1)) pixels(pos + 2) = CByte(255 - pixels(pos + 2)) Next Next 'ピクセルデータを元に戻す System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, pixels.Length) 'ロックを解除する img.UnlockBits(bmpData) End Sub 'PictureBox1のClickイベントハンドラ Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles PictureBox1.Click 'ネガティブイメージにする画像 Dim img As Image = Image.FromFile("C:\test\1.bmp") 'ネガティブイメージに変換 ChangeToNegativeImage(img) 'PictureBox1に表示 If Not (PictureBox1.Image Is Nothing) Then PictureBox1.Image.Dispose() End If PictureBox1.Image = img End Sub
//using System.Drawing; //using System.Drawing.Imaging; /// <summary> /// 指定された画像をネガティブイメージに変換する /// </summary> /// <param name="img">変換する画像</param> public static void ChangeToNegativeImage(Bitmap img) { //1ピクセルあたりのバイト数を取得する PixelFormat pixelFormat = img.PixelFormat; int pixelSize = Image.GetPixelFormatSize(pixelFormat) / 8; if (pixelSize < 3 || 4 < pixelSize) { throw new ArgumentException( "1ピクセルあたり24または32ビットの形式のイメージのみ有効です。", "img"); } //または次のように元の画像とは異なるPixelFormatでLockBitsすることも可能 //この場合、UnlockBitsで元のPixelFormatに戻る //ただし、元のPixelFormatとLockBits時のPixelFormatが異なる場合は、 //変更した色とは異なる色になる可能性がある //pixelFormat = PixelFormat.Format32bppArgb; //pixelSize = 4; //Bitmapをロックする BitmapData bmpData = img.LockBits( new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, pixelFormat); if (bmpData.Stride < 0) { img.UnlockBits(bmpData); throw new ArgumentException( "ボトムアップ形式のイメージには対応していません。", "img"); } //ピクセルデータをバイト型配列で取得する IntPtr ptr = bmpData.Scan0; byte[] pixels = new byte[bmpData.Stride * img.Height]; System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, pixels.Length); //すべてのピクセルの色を反転させる for (int y = 0; y < bmpData.Height; y++) { for (int x = 0; x < bmpData.Width; x++) { //ピクセルデータでのピクセル(x,y)の開始位置を計算する int pos = y * bmpData.Stride + x * pixelSize; //青、緑、赤の色を変更する pixels[pos] = (byte)(255 - pixels[pos]); pixels[pos + 1] = (byte)(255 - pixels[pos + 1]); pixels[pos + 2] = (byte)(255 - pixels[pos + 2]); } } //ピクセルデータを元に戻す System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, pixels.Length); //アンセーフコードを使うと、以下のようにもできる //unsafe //{ // byte* pixelPtr = (byte*)bmpData.Scan0; // for (int y = 0; y < bmpData.Height; y++) // { // for (int x = 0; x < bmpData.Width; x++) // { // //ピクセルデータでのピクセル(x,y)の開始位置を計算する // int pos = y * bmpData.Stride + x * pixelSize; // //青、緑、赤の色を変更する // pixelPtr[pos] = (byte)(255 - pixelPtr[pos]); // pixelPtr[pos + 1] = (byte)(255 - pixelPtr[pos + 1]); // pixelPtr[pos + 2] = (byte)(255 - pixelPtr[pos + 2]); // } // } //} //ロックを解除する img.UnlockBits(bmpData); } //PictureBox1のClickイベントハンドラ private void PictureBox1_Click(object sender, EventArgs e) { //ネガティブイメージにする画像 Bitmap img = new Bitmap(@"C:\test\1.bmp"); //ネガティブイメージに変換 ChangeToNegativeImage(img); //PictureBox1に表示 if (PictureBox1.Image != null) { PictureBox1.Image.Dispose(); } PictureBox1.Image = img; }
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。