[C#] 濾鏡筆記 – LockBits影像處理 + 浮雕效果

2012-12-09

 

這幾天被斗哥一直碎念,為什麼不用 LockBits 處理

其實是不知道怎麼起筆..

簡單的說來當一張 Bitmap 被轉為   Format24bppRgb 一長串的數值..

轉成 16 進位大概會長這樣 …

2012-10-04_130923

簡單解釋一下 一開始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] 是紅色


結果:



2012-10-04_130947



透過這樣處理會快非常的多 …



浮雕效果



浮雕效果原理 現正 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;
 
 
 }


結果:



2012-10-04_131004



很久以前的理解   如果有任何指教 鞭小力一下...T.T..



參考:



http://blog.csdn.net/jiangxinyu/article/details/6222302


http://www.guan8.net/Java/242899.html



 


當麻許的超技八 2014 | Donma Hsu Design.