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);
}
}
}