開発環境 Microsoft Visual Studio Community 2017
実行環境 Microsoft Windows 10 Home (64-bit)
プロジェクトの種類 Visual C# / Windows フォーム アプリケーション (.NET Framework)
プロジェクト名 BmpTest

参考

Form1.cs
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace BmpTest
{
    public partial class Form1 : Form
    {
        private Stopwatch sw;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            const int size = 300;
            const double half = size / 2.0;
 
            Bitmap bmp = new Bitmap(size, size);
            using(Graphics g = Graphics.FromImage(bmp))
            {
                for (var y = 0; y < bmp.Height; y++)
                {
                    var dy = (y - half) / half;
                    var dyy = dy * dy;
                    for (var x = 0; x < bmp.Width; x++)
                    {
                        var dx = (x - half) / half;
                        var dxx = dx * dx;
                        var h = Math.Atan2(-dy, dx) * 180 / Math.PI;
                        var v = 1 - (dxx + dyy);
                        var c = hsv(h, v);
                        bmp.SetPixel(x, y, c);
                    }
                }
            }
            pictureBox1.Image = bmp;
            pictureBox2.Image = (Image)bmp.Clone();
            pictureBox3.Image = (Image)bmp.Clone();
            pictureBox4.Image = (Image)bmp.Clone();
 
            sw = new Stopwatch();
        }
 
        private Color hsv(double h, double v)
        {
            double r = v * get_v(h);
            double g = v * get_v(h - 120);
            double b = v * get_v(h - 240);
            return Color.FromArgb(u8(r), u8(g), u8(b));
        }
 
        private double get_v(double ph)
        {
            ph %= 360;
            if (ph < 0) ph += 360;
            double v = (ph < 180) ? (2 - ph / 60) : (ph / 60 - 4);
            return Math.Min(Math.Max(v, 0), 1);
        }
 
        private int u8(double x)
        {
            int y = (int)(Math.Floor(x * 256));
            return Math.Min(Math.Max(y, 0), 255);
        }
 
        private void stop(Label label)
        {
            sw.Stop();
            label.Text = $"{sw.ElapsedMilliseconds}ms";
            sw.Reset();
        }
 
        // 1. SetPixel方式
        private void button1_Click(object sender, EventArgs e)
        {
            sw.Start();
            Bitmap bmp = (Bitmap)pictureBox1.Image;
 
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    Color c = bmp.GetPixel(x, y);
                    bmp.SetPixel(x, y, Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B));
                }
            }
            pictureBox1.Invalidate();
            stop(label1);
        }
 
        // 2. Marshal方式
        private void button2_Click(object sender, EventArgs e)
        {
            sw.Start();
            Bitmap bmp = (Bitmap)pictureBox2.Image;
            int pixelSize = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
            BitmapData data = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size),
                ImageLockMode.ReadWrite, bmp.PixelFormat);
            IntPtr ptr = data.Scan0;
            byte[] pixels = new byte[data.Stride * bmp.Height];
            Marshal.Copy(ptr, pixels, 0, pixels.Length);
 
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    int pos = y * data.Stride + x * pixelSize;
                    pixels[pos + 0] = (byte)(255 - pixels[pos + 0]);
                    pixels[pos + 1] = (byte)(255 - pixels[pos + 1]);
                    pixels[pos + 2] = (byte)(255 - pixels[pos + 2]);
                }
            }
            Marshal.Copy(pixels, 0, ptr, pixels.Length);
            bmp.UnlockBits(data);
            pictureBox2.Invalidate();
            stop(label2);
        }
 
        // 3. unsafe方式
        private void button3_Click(object sender, EventArgs e)
        {
            sw.Start();
            Bitmap bmp = (Bitmap)pictureBox3.Image;
            int pixelSize = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
            BitmapData data = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size),
                ImageLockMode.ReadWrite, bmp.PixelFormat);
            unsafe
            {
                byte* pixels = (byte*)data.Scan0.ToPointer();
                for (int y = 0; y < bmp.Height; y++)
                {
                    for (int x = 0; x < bmp.Width; x++)
                    {
                        int pos = y * data.Stride + x * pixelSize;
                        pixels[pos + 0] = (byte)(255 - pixels[pos + 0]);
                        pixels[pos + 1] = (byte)(255 - pixels[pos + 1]);
                        pixels[pos + 2] = (byte)(255 - pixels[pos + 2]);
                    }
                }
            }
            bmp.UnlockBits(data);
 
            pictureBox3.Invalidate();
            stop(label3);
        }
 
        // 4. Matrix方式
        private void button4_Click(object sender, EventArgs e)
        {
            sw.Start();
            Bitmap bmp = (Bitmap)pictureBox4.Image;
            float[][] mat = {
                new float[] { -1,  0,  0, 0, 0 },
                new float[] {  0, -1,  0, 0, 0 },
                new float[] {  0,  0, -1, 0, 0 },
                new float[] {  0,  0,  0, 1, 0 },
                new float[] {  1,  1,  1, 0, 1 } };
            ColorMatrix cm = new ColorMatrix(mat);
            ImageAttributes ia = new ImageAttributes();
            ia.SetColorMatrix(cm);
            using (var g = Graphics.FromImage(bmp))
            {
                g.DrawImage(pictureBox4.Image, new Rectangle(Point.Empty, bmp.Size),
                    0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
            }
            pictureBox4.Invalidate();
            stop(label4);
        }
    }
}
 

最終更新:2018年12月11日 18:22
添付ファイル