C#中可以利用非安全指针对位图进行处理,下面利用MSDN的一个例子进行讲解:
Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
//读取本地图像 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, bmp.PixelFormat); //BitmapData 指定 Bitmap 的属性,如大小、像素格式、像素数据在内存中的始地址以及每个扫描行的长度(步幅)。
//lockbit将位图锁定到内存中,这样做主要是增加效率,如果速度不是主要因素的话,建议使用bitmap的setpixel和getpixel方法,省去了使用不安全指针的麻烦。
IntPtr ptr = bmpData.Scan0;
//Scan0获取或设置位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行。简言之就是把当前指针设置在图像最左上角的位置。 int bytes = bmp.Width * bmp.Height * 3;
byte[] rgbValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
for (int counter = 0; counter < rgbValues.Length; counter+=3) System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); //将数据从托管数组复制到非托管内存指针,或从非托管内存指针复制到托管数组,此处为前者。
bmp.UnlockBits(bmpData);
//解锁 e.Graphics.DrawImage(bmp, 0, 150);
想对lockbit有所了解的同学可以看《Using the LockBits method to access image data》。
下面附上一个实例,其中原理是凭着研一时的数字图像处理课。
马赛克范例
很多图片处理的算法从原理上讲其实非常简单,难点往往在如何去写算法实现它,更加难的就是如何去优化实现的算法。 马赛克算法很简单,说白了就是把一张图片分割成若干个val * val像素的小区块(可能在边缘有零星的小块,但不影响整体算法),每个小区块的颜色都是相同的。为了方便起见,我们不妨让这个颜色就用该区域最左上角的那个点的颜色。当然还可以有其他方法,比如取区块中间点的颜色,或区块中随机点的颜色作代表等等。 下面的示意图就是取val=2的结果。 原图像素 |