浮雕效果透過計算相鄰像素差值產生立體感:
(x, y) 與右下相鄰像素 (x+1, y+1) 的 RGB 值。R' = |R1 - R2 + 128|G' = |G1 - G2 + 128|B' = |B1 - B2 + 128|private void button1_Click(object sender, EventArgs e)
{
try
{
int Height = this.pictureBox1.Image.Height;
int Width = this.pictureBox1.Image.Width;
Bitmap newBitmap = new Bitmap(Width, Height);
Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image;
Color pixel1, pixel2;
for (int x = 0; x < Width - 1; x++)
{
for (int y = 0; y < Height - 1; y++)
{
int r = 0, g = 0, b = 0;
pixel1 = oldBitmap.GetPixel(x, y);
pixel2 = oldBitmap.GetPixel(x + 1, y + 1);
r = Math.Abs(pixel1.R - pixel2.R + 128);
g = Math.Abs(pixel1.G - pixel2.G + 128);
b = Math.Abs(pixel1.B - pixel2.B + 128);
// 限制範圍 0-255
r = Math.Max(0, Math.Min(255, r));
g = Math.Max(0, Math.Min(255, g));
b = Math.Max(0, Math.Min(255, b));
newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
}
}
this.pictureBox1.Image = newBitmap;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "資訊提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
GetPixel/SetPixel 效能極差,大圖處理應使用 Bitmap.LockBits 直接操作記憶體。Parallel.For 多執行緒加速。public static Bitmap EmbossFilter(Bitmap source)
{
Bitmap result = new Bitmap(source.Width, source.Height, source.PixelFormat);
Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
var srcData = source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
var dstData = result.LockBits(rect, ImageLockMode.WriteOnly, result.PixelFormat);
int bytes = Math.Abs(srcData.Stride) * source.Height;
byte[] srcBytes = new byte[bytes];
byte[] dstBytes = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(srcData.Scan0, srcBytes, 0, bytes);
int stride = srcData.Stride;
int width = source.Width;
int height = source.Height;
for (int y = 0; y < height - 1; y++)
{
for (int x = 0; x < width - 1; x++)
{
int idx1 = y * stride + x * 4;
int idx2 = (y + 1) * stride + (x + 1) * 4;
int r = Math.Abs(srcBytes[idx1 + 2] - srcBytes[idx2 + 2] + 128);
int g = Math.Abs(srcBytes[idx1 + 1] - srcBytes[idx2 + 1] + 128);
int b = Math.Abs(srcBytes[idx1] - srcBytes[idx2] + 128);
dstBytes[idx1 + 2] = (byte)Math.Clamp(r, 0, 255);
dstBytes[idx1 + 1] = (byte)Math.Clamp(g, 0, 255);
dstBytes[idx1] = (byte)Math.Clamp(b, 0, 255);
dstBytes[idx1 + 3] = 255; // Alpha
}
}
System.Runtime.InteropServices.Marshal.Copy(dstBytes, 0, dstData.Scan0, bytes);
source.UnlockBits(srcData);
result.UnlockBits(dstData);
return result;
}
同樣原理可實作:
• 雕刻效果:使用左上像素與右下像素差值
• 邊緣偵測:Sobel、Prewitt 算子
• 銳化:拉普拉斯算子