C# BitmapData使用

來源:互聯網
上載者:User

標籤:

C# BitmapData使用

msdn關於BitmapData原文解釋地址:
http://msdn.microsoft.com/zh-cn/library/5ey6h79d(v=vs.110).aspx
以下是msdn原文給出的例子

private void LockUnlockBitsExample(PaintEventArgs e){    // Create a new bitmap.    Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");    // Lock the bitmap's bits.      Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);    System.Drawing.Imaging.BitmapData bmpData =        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,        bmp.PixelFormat);    // Get the address of the first line.    IntPtr ptr = bmpData.Scan0;    // Declare an array to hold the bytes of the bitmap.    int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;     byte[] rgbValues = new byte[bytes];    // Copy the RGB values into the array.    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);    // Set every third value to 255. A 24bpp bitmap will look red.      for (int counter = 2; counter < rgbValues.Length; counter += 3)        rgbValues[counter] = 255;    // Copy the RGB values back to the bitmap    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);    // Unlock the bits.    bmp.UnlockBits(bmpData);    // Draw the modified image.    e.Graphics.DrawImage(bmp, 0, 150);}
原文給出的例子已經可以理解出部分意思了,按照土鱉國王本人實驗然後理解如下,如有誤還請大神斧正
C#專門為影像處理提供了BitmapData,這個是真正的對位元影像的處理,首先將位元影像鎖定到記憶體中,然後對位元影像的每一個像素進行處理,效率還是非常高的,下面先給出偶自己轉化映像灰階值的例子,以函數的形式給出
以便需要的朋友直接可以使用,可以說是任何操作都是依次為基礎的,如果覺得注釋太多,可將注釋直接刪除,然後將代碼烤白可直接使用,指標法效率更高,這裡只給出記憶體法先理解,然後便可大展身手了,哈哈

<span style="font-family:Microsoft YaHei;">/// 擷取灰階值返回byte[]/// <summary>/// 擷取灰階值返回byte[]/// </summary>/// <param name="srcBmp">源映像</param>/// <param name="rect">要鎖定的映像地區</param>/// <returns>返回byte[]</returns>public static byte[] GetGrayArray(Bitmap srcBmp, Rectangle rect){    //將Bitmap鎖定到系統記憶體中    //rect是指源映像中需要鎖定那一塊矩形地區進行處理    //ImageLockMode.ReadWrite是指對映像出操作的許可權,枚舉有唯讀,唯寫,使用者輸入緩衝區,還是讀寫    //PixelFormat.Format24bppRgb    //參數確定了該映像資訊時rgb儲存還是Argb儲存,如果是Format24ppRgb則處理的映像像素就是BGR方式儲存,我們這裡沒有特別指出,均是Format24bppRgb方式儲存處理    BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);    //位元影像中第一個像素資料的地址。它也可以看成是位元影像中的第一個掃描行    IntPtr srcPtr = srcBmpData.Scan0;    //將Bitmap對象的資訊存放到byte數組中    //假設本映像的寬度和高度為5*3    /*    1  2  3  4  5  6  7  8  9  10  11 12 13 14 15  //這裡儲存為一維數組,所以是一行,    寬度為5,高度為3,則像素總數為15,這裡要清楚,每一個像素是rgb三個值,故而,一維數組中    儲存為    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14    15...44    這裡分行是為了便於理解,一維數組儲存類似是一行,但是我們的映像的寬度是5也就是我們映像的第一行是0123...到14,下一行是15...29,下一行是30...44,高度為3,所以就是3行    012 345 678 91011 121314    bgr bgr bgr  bgr   bgr      151617  181920  ...    bgr      bgr    ...    這樣儲存    */    //所以才有了這裡的*3就是指一個像素是三個分量值    int scanWidth = rect.Width * 3;    //而每行的實際的位元組數將變成大於等於它的那個離它最近的4的整倍數,此時的實際位元組數就是Stride,如果上面的第三個參數Format24ppRgb如果設定為Format32ppRgb,這個時候儲存的時候就是4位儲存一個像素,如果是Format32bppArgb同樣也是4為儲存一個像素,這4位除了bgr三個分量之外還有透明度A的值    //至於為什麼是24,32,這是因為電腦儲存資料為8bit儲存1個位元組,    //bgr3個就是3*8=24,4個就是4*8=32了,為什麼是16,8位等,索引圖等原理是一樣的    //int srcStride = srcBmpData.Stride;    int src_bytes = scanWidth * rect.Height;  //這裡就是計算出了需要儲存的像素所佔用的空間大小    byte[] srcValues = new byte[src_bytes];  //定義源映像的元資訊    byte[] grayValues = new byte[rect.Width * rect.Height];  //定義轉化為灰階後需要儲存的數組    //複製GRB資訊到byte數組,將從srcPtr開始的第一個掃描行開始掃描資訊,然後讀取到srcValues數組中    Marshal.Copy(srcPtr, srcValues, 0, src_bytes);    //解鎖位元影像    srcBmp.UnlockBits(srcBmpData);  //讀取完元資訊,這裡就不用了,一定要記得解鎖,否則會報錯    //下面就是你想怎麼處理都成了,,灰階化,轉換空間模式,除雜訊,腐蝕,膨脹,反色,二值化等等均可    //灰階化處理    int m = 0, j = 0;    int k = 0;    byte gray;    //根據重要性及其它指標,將三個分量以不同的權值進行加權平均。由於人眼對綠色的敏感最高,對藍色敏感最低,因此,按下式對RGB三分量進行加權平均能得到較合理的灰階映像    //根據Y = 0.299*R + 0.587*G + 0.114*B  //加權平均法    for (int i = 0; i < rect.Height; i++)    {        for (j = 0; j < rect.Width; j++)        {            //注意位元影像結構中RGB按BGR的順序儲存            k = 3 * j;            gray = (byte)(srcValues[i * scanWidth + k + 2] * 0.299                 + srcValues[i * scanWidth + k + 1] * 0.587                 + srcValues[i * scanWidth + k + 0] * 0.114);            grayValues[m] = gray;  //將灰階值存到double的數組中            m++;        }    }    return grayValues;}//接下來就很簡單了,下面在給出獲得到灰階值儲存為2位元組的方法,按照習慣二維處理起來比較好理解/// 擷取灰階值存到二維double數組中,這個是將rgb轉化為灰階值/// <summary>/// 擷取灰階值存到二維double數組中,這個是將rgb轉化為灰階值/// </summary>/// <param name="srcBmp"></param>/// <returns>2Dimension</returns>public static byte[,] GetGrayArray2D(Bitmap srcBmp,Rectangle rect){    int width = rect.Width;    int height = rect.Height;    BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);    IntPtr srcPtr = srcBmpData.Scan0;    int scanWidth = width * 3;    int src_bytes = scanWidth * height;    //int srcStride = srcBmpData.Stride;    byte[] srcRGBValues = new byte[src_bytes];    byte[,] grayValues = new byte[height, width];    //RGB[] rgb = new RGB[srcBmp.Width * rows];    //複製GRB資訊到byte數組    Marshal.Copy(srcPtr, srcRGBValues, 0, src_bytes);    //解鎖位元影像    srcBmp.UnlockBits(srcBmpData);    //灰階化處理    int m = 0, i = 0, j = 0;  //m表示行,j表示列    int k = 0;    byte gray;    for (i = 0; i < height; i++)  //只擷取圖片的rows行像素值    {        for (j = 0; j < width; j++)        {            //只處理每行中映像像素資料,捨棄未用空間            //注意位元影像結構中RGB按BGR的順序儲存            k = 3 * j;            gray = (byte)(srcRGBValues[i * scanWidth + k + 2] * 0.299                 + srcRGBValues[i * scanWidth + k + 1] * 0.587                 + srcRGBValues[i * scanWidth + k + 0] * 0.114);            grayValues[m, j] = gray;  //將灰階值存到double的數組中        }        m++;    }    return grayValues;}//此方法是直接得到灰階圖/// 擷取灰階映像,將制定圖片轉化為灰階圖/// <summary>/// 擷取灰階映像,將制定圖片轉化為灰階圖/// </summary>/// <param name="srcBmp"></param>/// <returns></returns>public static Bitmap GetGrayImage(Bitmap srcBmp){    Rectangle rect = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);    BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);    IntPtr srcPtr = srcBmpData.Scan0;    int scanWidth = srcBmpData.Width * 3;    int src_bytes = scanWidth * srcBmp.Height;    byte[] srcRGBValues = new byte[src_bytes];    Marshal.Copy(srcPtr, srcRGBValues, 0, src_bytes);    //灰階化處理    int k = 0;    for (int i = 0; i < srcBmp.Height; i++)    {        for (int j = 0; j < srcBmp.Width; j++)        {            k = j * 3;            //0.299*R + 0.587*G + 0.144*B = 亮度或灰階            //只處理每行中映像像素資料,捨棄未用空間            //注意位元影像結構中RGB按BGR的順序儲存            byte intensity = (byte)(srcRGBValues[i * scanWidth + k + 2] * 0.299                 + srcRGBValues[i * scanWidth + k + 1] * 0.587                 + srcRGBValues[i * scanWidth + k + 0] * 0.114);            srcRGBValues[i * scanWidth + k + 0] = intensity;            srcRGBValues[i * scanWidth + k + 1] = intensity;            srcRGBValues[i * scanWidth + k + 2] = intensity;        }    }    Marshal.Copy(srcRGBValues, 0, srcPtr, src_bytes);    //解鎖位元影像    srcBmp.UnlockBits(srcBmpData);    return srcBmp;}</span>
以上就是C# BitmapData的使用介紹,首先融會貫通,其次舉一反三,方可熟能生巧


C# BitmapData使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.