[C#] 濾鏡筆記 – LockBits影像處理 + 浮雕效果
2012-12-09
這幾天被斗哥一直碎念,為什麼不用 LockBits 處理
其實是不知道怎麼起筆..
簡單的說來當一張 Bitmap 被轉為 Format24bppRgb 一長串的數值..
轉成 16 進位大概會長這樣 …
簡單解釋一下 一開始Scan0 主要就是第一個 Pixel 的第一個數值 …
紅色線條就代表一個 Pixel , 灰色框框部分是所謂的 offset 感覺像是畸零地得味道
他代表圖片換行所以在跑迴圈的時候會跳過..
至於要怎麼知道 offset 要跳過幾個..
簡單的來說 因為使用 Format24bppRgb 所以 三個為一組
offset= stride(步幅, 跨步值) - 圖片寬度 x 3
其中的跨步值 可以透過 LockBits 取得 BitmapData 後取得..
至於藍色箭頭表示為每一次我的 p 指標的位置
所以當指向 每一個定位點 p[0] 是藍色 ,p[1] 是綠色,p[2] 是紅色,
用同樣方法我改寫前幾天寫的 調成灰階的效果:
C# code :
public Bitmap AdjustToGrey(Bitmap src)
{
// 依照 Format24bppRgb 每三個表示一 Pixel 0: 藍 1: 綠 2: 紅
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
// 抓住第一個 Pixel 第一個數值
byte* p = (byte*)(void*)bitmapData.Scan0;
// 跨步值 - 寬度 *3 可以算出畸零地 之後跳到下一行
int nOffset = bitmapData.Stride - src.Width * 3;
for (int y = 0; y < src.Height; y++)
{
for (int x = 0; x < src.Width; x++)
{
// 為了理解方便 所以特地在命名
int r, g, b;
r = p[2];
g = p[1];
b = p[0];
p[0] = p[1] = p[2] = (byte)(.33 * r + .33 * g + .33 * b);
// 跳去下一個 Pixel
p += 3;
}
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src;
}
其中特別注意 p[0] 是藍色 ,p[1] 是綠色,p[2] 是紅色
結果:
透過這樣處理會快非常的多 …
浮雕效果
浮雕效果原理 現正 Pixel 的 RGB - 取得下一個 Pixel 的 RGB 並且加上 128
C# Code :
public Bitmap AdjustToStone(Bitmap src)
{
// 依照 Format24bppRgb 每三個表示一 Pixel 0: 藍 1: 綠 2: 紅
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
// 抓住第一個 Pixel 第一個數值
byte* p = (byte*)(void*)bitmapData.Scan0;
// 跨步值 - 寬度 *3 可以算出畸零地 之後跳到下一行
int nOffset = bitmapData.Stride - src.Width * 3;
for (int y = 0; y < src.Height ; ++y)
{
for (int x = 0; x < src.Width; ++x)
{
// 為了理解方便 所以特地在命名
int r, g, b;
// 先取得下一個 Pixel
var q = p + 3;
r = Math.Abs(p[2] - q[2] + 128);
r = r < 0 ? 0 : r;
r = r > 255 ? 255 : r;
p[2] = (byte)r;
g = Math.Abs(p[1] - q[1] + 128);
g = g < 0 ? 0 : g;
g = g > 255 ? 255 : g;
p[1] = (byte)g;
b = Math.Abs(p[0] - q[0] + 128);
b = b < 0 ? 0 : b;
b = b > 255 ? 255 : b;
p[0] = (byte)b;
// 跳去下一個 Pixel
p += 3;
}
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src;
}
結果:
很久以前的理解 如果有任何指教 鞭小力一下...T.T..
參考:
http://blog.csdn.net/jiangxinyu/article/details/6222302
http://www.guan8.net/Java/242899.html