提高c#位图操作的速度[抄袭之作]
众所周知,c#里 bitmap类里的getpixel和setpixel函数的效率很慢,一个解决办法是使用bitmapData对位图进行指针操作,
而在用指针在进行读取的时候,对于不用格式(PixelFormat)的位图,要进行区分。十分的麻烦。前几天无意中在codeproject上看到一篇文章,
对于bitmapData的进行了封装,相当的漂亮,所以就抄了过来,仅供参考,原文在这里。
代码如下:
1 public class LockBitmap:IDisposable
2 {
3 Bitmap source = null;
4 IntPtr Iptr = IntPtr.Zero;
5 BitmapData bitmapData = null;
6 int step=0;
7 public byte[] Pixels { get; set; }
8 public int Depth { get; private set; }
9 public int Width { get; private set; }
10 public int Height { get; private set; }
11
12 public LockBitmap(Bitmap source)
13 {
14 this.source = source;
15 LockBits();
16 }
17
18 ///<summary>
19 /// Lock bitmap data
20 ///</summary>
21 private void LockBits()
22 {
23 try
24 {
25 // Get width and height of bitmap
26 Width = source.Width;
27 Height = source.Height;
28
29 // get total locked pixels count
30 int PixelCount = Width * Height;
31
32 // Create rectangle to lock
33 Rectangle rect = new Rectangle(0, 0, Width, Height);
34
35 // get source bitmap pixel format size
36 Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
37
38 // Check if bpp (Bits Per Pixel) is 8, 24, or 32
39 if (Depth != 8 && Depth != 24 && Depth != 32)
40 {
41 throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
42 }
43
44 // Lock bitmap and return bitmap data
45 bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
46 source.PixelFormat);
47
48 // create byte array to copy pixel values
49 step = Depth / 8;
50 Pixels = new byte[PixelCount * step];
51 Iptr = bitmapData.Scan0;
52
53 // Copy data from pointer to array
54 Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
55 }
56 catch (Exception ex)
57 {
58 throw ex;
59 }
60 }
61
62 ///<summary>
63 /// Unlock bitmap data
64 ///</summary>
65 private void UnlockBits()
66 {
67 try
68 {
69 // Copy data from byte array to pointer
70 Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);
71
72 // Unlock bitmap data
73 source.UnlockBits(bitmapData);
74 }
75 catch (Exception ex)
76 {
77 throw ex;
78 }
79 }
80 public void Dispose()
81 {
82 UnlockBits();
83 }
84 ///<summary>
85 /// Get the color of the specified pixel
86 ///</summary>
87 ///<param name="x"></param>
88 ///<param name="y"></param>
89 ///<returns></returns>
90 public Color GetPixel(int x, int y)
91 {
92 Color clr = Color.Empty;
95
96 // Get start index of the specified pixel
97 int i = ((y * Width) + x) * step;
98
99 if (i > Pixels.Length - step)
100 throw new IndexOutOfRangeException();
101
102 if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
103 {
104 byte b = Pixels[i];
105 byte g = Pixels[i + 1];
106 byte r = Pixels[i + 2];
107 byte a = Pixels[i + 3]; // a
108 clr = Color.FromArgb(a, r, g, b);
109 }
110 if (Depth == 24) // For 24 bpp get Red, Green and Blue
111 {
112 byte b = Pixels[i];
113 byte g = Pixels[i + 1];
114 byte r = Pixels[i + 2];
115 clr = Color.FromArgb(r, g, b);
116 }
117 if (Depth == 8)
118 // For 8 bpp get color value (Red, Green and Blue values are the same)
119 {
120 byte c = Pixels[i];
121 clr = Color.FromArgb(c, c, c);
122 }
123 return clr;
124 }
125
126 ///<summary>
127 /// Set the color of the specified pixel
128 ///</summary>
129 ///<param name="x"></param>
130 ///<param name="y"></param>
131 ///<param name="color"></param>
132 public void SetPixel(int x, int y, Color color)
133 {
134 // Get start index of the specified pixel
135 int i = ((y * Width) + x) * step;
136
137 if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha
138 {
139 Pixels[i] = color.B;
140 Pixels[i + 1] = color.G;
141 Pixels[i + 2] = color.R;
142 Pixels[i + 3] = color.A;
143 }
144 if (Depth == 24) // For 24 bpp set Red, Green and Blue
145 {
146 Pixels[i] = color.B;
147 Pixels[i + 1] = color.G;
148 Pixels[i + 2] = color.R;
149 }
150 if (Depth == 8)
151 // For 8 bpp set color value (Red, Green and Blue values are the same)
152 {
153 Pixels[i] = color.B;
154 }
155 }
156 }