目前操做位圖的主流方法有三種:數組
一、基於Bitmap像素的處理方法,以GetPixel()和SetPixel()方法爲主。方法調用簡單,可是效率偏低。ide
二、基於內存的像素操做方法,以System.Runtime.InteropServices.Marshal.Copy()方法將數據變爲非託管資源,操做後再寫入內存。spa
三、基於指針的操做方式,效率最高,可是對使用者的能力有要求,能力不夠者容易形成內存溢出。指針
第二種方法的一個實例:code
1 //大圖逐行遍歷,y爲行索引 2 for (var y = 0; y < destHeight; y++) 3 { 4 //小圖。把一行數據讀入數組。第一個參數是起始位。 5 System.Runtime.InteropServices.Marshal.Copy(srcScan0 + y * srcStride, srcBuffer, 0, srcStride); 6 //大圖。 7 System.Runtime.InteropServices.Marshal.Copy(dstScan0 + y * dstStride, dstBuffer, 0, dstStride); 8 9 //大圖逐列,rgb三色.(與源碼相比作了修改,遍歷長度減少,數值由於是灰度值,計算了變爲了三分之一。) 10 for (var x = 0; x < destWidth; x ++) 11 { 12 //字節總索引 13 int fullIndex = 3*x; 14 //相乘,再除以255。返回一個byte 15 //dstBuffer[x] = channelProcessFunction(ref srcBuffer[x], ref dstBuffer[x]); 16 var blendValue = channelProcessFunction(ref srcBuffer[fullIndex], ref dstBuffer[fullIndex]); 17 dstBuffer[fullIndex + 2] = blendValue; 18 dstBuffer[fullIndex + 1] = blendValue; 19 dstBuffer[fullIndex] = blendValue; 20 } 21 //寫回託管內存 22 System.Runtime.InteropServices.Marshal.Copy(dstBuffer, 0, dstScan0 + y * dstStride, dstStride); 23 }
而對於灰度圖的處理,能夠使用調整gamma值的方式。對於灰度圖處理的一個實例:orm
1 /// <summary> 2 /// 把小圖片按照權重,重設gamma值,從新渲染。可獲得加權重後的小圖,背景爲白色,非透明。 3 /// </summary> 4 /// <param name="image">小圖片</param> 5 /// <param name="weight">權重</param> 6 /// <returns>加權重後的小圖,背景爲白色,非透明</returns> 7 private static Bitmap ApplyHeatValueToImage(Bitmap image, float weight) 8 { 9 //新建臨時位圖 10 var tempImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); 11 12 using (var g = Graphics.FromImage(tempImage)) 13 { 14 //把權重參數映射爲[0.1-5],以便後面進行gamma的矯正。gamma值正常範圍爲1.0 - 2.2 15 //此處拓展,能夠讓色彩更加intense 16 //gamma值可用來進行灰度值層面的明暗矯正,改善失真。 17 ////I want to make the color more intense (White/bright) 18 if (weight < 0.02f) weight = 0.02f;//最小0.02 19 weight *= 5f; 20 if (weight > 5f) weight = 5f; 21 22 // Create ImageAttributes 23 var ia = new ImageAttributes(); 24 25 //Gamma values range from 0.1 to 5.0 (normally 0.1 to 2.2), with 0.1 being the brightest and 5.0 the darkest. 26 //Convert the 100% to a range of 0.1-5 by multiplying it by 5 27 ia.SetGamma(weight, ColorAdjustType.Bitmap); 28 29 //在image中 重繪 30 // Draw Image with the attributes 31 g.DrawImage(image, 32 new Rectangle(0, 0, image.Width, image.Height),//這裏若是size設小一點,能夠對目標圖像進行縮放。若是小於Graphics的尺寸,則會出現白邊 33 0, 0, image.Width, image.Height,//這裏能夠對源圖像進行裁剪。 34 GraphicsUnit.Pixel, ia); 35 } 36 //New dot with a different intensity 37 return tempImage; 38 }