淺談.NET圖片快速處理的幾種方法
這里首先要介紹一個類System.Drawing.Imaging.BitmapData,直接實例化這個類沒有用處,我們需要將一個Bitmap鎖定到內存中,來獲取一個BitmapData的實例。.NET圖片快速處理方法如下:
使用Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)或者它的另一個重載Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)來將圖像數據鎖定到內存中,以此來獲取一個與指定圖片相關聯的BitmapData實例。
在BitmapData中有一個重要的屬性Scan0,它是一個指針,指向了圖片數據所在內存的***個位置。使用內存跟蹤,將Scan0的值填入地址中,可以看到內存的分配情況(Format32bppArgb顏色深度):
這些值與圖片像素的對應關系是這樣的:
現在我們可以使用System.Runtime.InteropServices.Marshal.WriteByte(IntPtr ptr, byte val)的方法來更改指定位置的像素值了,修改后只要再調用一次Bitmap.UnlockBits(BitmapData bitmapdata)來解鎖內存就可以了,例如:
- private void LockUnlockBitsExample(PaintEventArgs e)
- {
- Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
- Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
- System.Drawing.Imaging.BitmapData bmpbmpData =
- bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
- bmp.PixelFormat);
- IntPtr ptr = bmpData.Scan0;
- int bytes = bmp.Width * bmp.Height * 3;
- byte[] rgbValues = new byte[bytes];
- for (int counter = 0; counter < rgbValues.Length; counter += 3)
- {
- Marshal.WriteByte(ptr, counter, 255);
- }
- bmp.UnlockBits(bmpData);
- e.Graphics.DrawImage(bmp, 0, 0);
- }
此.NET圖片快速處理示例將圖片上所有像素的Red向量設置為255。運行此實例可以看到圖片變色了。
每次調用System.Runtime.InteropServices.Marshal.WriteByte(IntPtr ptr, byte val)的方法并不方便,因此我們構造一個ColorBgra類用來儲存這4個顏色向量,它的主要代碼是這樣的(參考自Paint.Net提供的源碼):
- [StructLayout(LayoutKind.Explicit)]
- public struct ColorBgra
- {
- [FieldOffset(0)]
- public byte B;
- [FieldOffset(1)]
- public byte G;
- [FieldOffset(2)]
- public byte R;
- [FieldOffset(3)]
- public byte A;
- /// <summary>
- /// Lets you change B, G, R, and A at the same time.
- /// </summary>
- [FieldOffset(0)]
- public uint Bgra;
- public override string ToString()
- {
- return "B: " + B + ", G: " + G + ", R: " + R + ", A: " + A;
- }
- }
使用這個類在聲明為unsafe的上下文中就可以通過計算偏移量的辦法尋址找到指定位置像素的地址(指針),例如在Format32bppArgb顏色深度的圖片中可以這樣計算:
- public unsafe ColorBgra* GetPointAddress(int x, int y)
- {
- return y * 4 + x;
- }
將計算返回的指針賦給ColorBgra*。之后使用如下方法:
- color->B = i; color ->G = i; color ->R = i; color ->A = i;
直接把值寫入內存中,實現.NET圖片快速處理操作。
【編輯推薦】