c#中完成圖片灰度化技巧詳解。本站提示廣大學習愛好者:(c#中完成圖片灰度化技巧詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是c#中完成圖片灰度化技巧詳解正文
客歲買了本數字圖象處置算法,一向都沒有看,前幾個禮拜都一向忙著任務上的活,趁這階段安閒點,玩一玩圖片處置,這玩意照樣異常成心思的。
之前我們在做Web上的用戶注冊時,平日都邑做一個驗證碼,年夜家都曉得用來避免暴力注冊的,固然提到驗證碼年夜家都曉得C#外面有一個Bitmap類專門用來處置圖片的,好吧,這一篇我們從最簡略的“圖片灰度化”說起。
一:圖片灰度化
我們都曉得,位圖是由一個一個像素點構成的,像素點能夠是白色,橙色,粉色等等,這些色彩我們都曉得是用RGB來表現的。
每一個色彩重量都是一個字節(0-255),所以普通情形下圖的像素點都是24位,固然還有32位,64位,當RGB是0-255之間的分歧值時,那末該像素點就出現“五彩缤紛”,而當RGB都是雷同的值是,則像素點出現“灰色”,假如年夜家玩過CSS的話,確定都曉得給一個字體的color平日都是#999999,#666666,#333333這些分歧深度的灰色。
1.盤算公式
上面我們該若何設置公道的灰度值呢?固然照樣用以後的RGB為模板,然後對RGB乘以一個公道的權重就ok了
Gary(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j);
2.編程
有了公式,完成起來就不成成績了。Bitmap類中有一個GetPixel/SetPixel,它可以獲得和設置以後的像素點。
static void Main(string[] args) { Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg"); for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { //取圖片以後的像素點 var color = bitmap.GetPixel(i, j); var gray = (int)(color.R * 0.299 + color.G * 0.587 + color.B * 0.114); //從新設置以後的像素點 bitmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } bitmap.Save(Environment.CurrentDirectory + "//2.jpg"); }
3.改良
下面這個辦法很簡略,Get/Set就Ok了,固然這是我們站在像素點這個角度來斟酌成績的,貌似只需O(N2)的時光便可以KO成績,然則Get/Set遠遠不是O(1)的,基於機能斟酌,我們能不克不及有更優的辦法,此時我們可以站在字節這個角度思慮,不外這裡我們要留意一個成績就是:好比圖片的width=21px,一個像素點占用3個字節,然則21個像素點紛歧定就占用63個字節,這是由於體系基於機能斟酌,在每行中寄存著一個“未用區域”,來確保圖片每行的byte數是4的倍數,那末若何去讀某一行的字節數呢?
C#外面有一個Stride屬性便可以用來獲得,很簡略吧。
static void Main(string[] args) { Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg"); //界說鎖定bitmap的rect的指定規模區域 Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); //加鎖區域像素 var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat); //位圖的首地址 var ptr = bitmapData.Scan0; //stride:掃描行 int len = bitmapData.Stride * bitmap.Height; var bytes = new byte[len]; //鎖定區域的像素值copy到byte數組中 Marshal.Copy(ptr, bytes, 0, len); for (int i = 0; i < bitmap.Height; i++) { for (int j = 0; j < bitmap.Width * 3; j = j + 3) { var color = bytes[i * bitmapData.Stride + j + 2] * 0.299 + bytes[i * bitmapData.Stride + j + 1] * 0.597 + bytes[i * bitmapData.Stride + j] * 0.114; bytes[i * bitmapData.Stride + j] = bytes[i * bitmapData.Stride + j + 1] = bytes[i * bitmapData.Stride + j + 2] = (byte)color; } } //copy回位圖 Marshal.Copy(bytes, 0, ptr, len); //解鎖 bitmap.UnlockBits(bitmapData); bitmap.Save(Environment.CurrentDirectory + "//3.jpg"); }