在本人的隨筆 《在c#中用指標操作圖片像素點》 中,介紹了兩種不安全的方法,優勢就在於時間效率上的提升,但是C#畢竟是安全性的語言,這裡就介紹一種執行效率很高的安全方法——
前幾天在圖書館裡發現了一本用C#講圖形學的書,其中就介紹了一種時間效率比指標法稍低的安全方法
//從檔案中獲得Bitmap對象 Bitmap bitmap = Bitmap.FromFile(fileName) as Bitmap;Rectangle rect =new Rectangle(0, 0, bitmap.Width, bitmap.Height);BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);IntPtr ptr = bmpData.Scan0;int count = bitmap.Width * bitmap.Height *3;byte[] rgbValues =newbyte[count]; //將資料從非託管記憶體指標複製到託管 8 位不帶正負號的整數數組,這個方法是重點 Marshal.Copy(ptr, rgbValues, 0, count);
for (int i =0; i < rgbValues.Length; i +=3) { //在這裡可以對相應位置上的像素進行讀取或設定 rgbValues[i +2] = (byte)(255- rgbValues[i +2]); //R rgbValues[i +1] = (byte)(255- rgbValues[i +1]); //G rgbValues[i] = (byte)(255- rgbValues[i]); //B}
//將一維的託管 8 位不帶正負號的整數數組中的資料複製到非託管記憶體指標。
Marshal.Copy(rgbValues, 0, ptr, count);
bitmap.UnlockBits(bmpData);
這個方法的關鍵就在於 Marshal.Copy(),這個函數有16個重載形式,分別用於非託管記憶體指標和託管數組間的相互轉化,這個例子中就用到了兩個重載形式,用於資料
在非託管記憶體和託管數組間的來回傳遞。其它的重載形式,MSDN上說明得很清楚,就不在這熬述了。
這種方法的時間效率和指標法相差無幾,測試了下。不過有一點就是這種方法還是只適用於對每個像素點進行同一操作,因為不能用X,Y進行兩維上的定點。估計是我沒有對映像的格式進行深入的研究,才沒法將一維的操作轉化為二維的,有待學習……