C#中的图像处理(附带生成马赛克范例)
2010-03-09 16:11
176 查看
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, System.Drawing.Imaging.ImageLockMode.ReadWrite,
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)
rgbValues[counter] = 255;
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的结果。
原图像素
ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ01
2345678
马赛克处理后
AACCEEG
AACCEEG
OOQQSSU
OOQQSSU
2244668
public static Bitmap KiMosaic(Bitmap b, int val)
{
if (b.Equals(null))
{
return null;
}
int w = b.Width;
int h = b.Height;
int stdR, stdG, stdB;
stdR = 0;
stdG = 0;
stdB = 0;
BitmapData srcData = b.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
byte* p = (byte*)srcData.Scan0.ToPointer();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
if (y % val == 0)
{
if (x % val == 0)
{
stdR = p[2]; stdG = p[1]; stdB = p[0];
}
else
{
p[0] = (byte)stdB;
p[1] = (byte)stdG;
p[2] = (byte)stdR;
}
}
else
{
// 复制上一行
byte * pTemp = p - srcData.Stride;
p[0] = (byte)pTemp[0];
p[1] = (byte)pTemp[1];
p[2] = (byte)pTemp[2];
}
p += 3;
} // end of x
p += srcData.Stride - w * 3;
} // end of y
b.UnlockBits(srcData);
}
return b;
}
先上原图:
![](http://hi.csdn.net/attachment/201003/9/82054_1268122561n1fa.jpg)
再上效果图
![](http://hi.csdn.net/attachment/201003/9/82054_1268122564SNuL.jpg)
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, System.Drawing.Imaging.ImageLockMode.ReadWrite,
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)
rgbValues[counter] = 255;
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的结果。
原图像素
ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ01
2345678
马赛克处理后
AACCEEG
AACCEEG
OOQQSSU
OOQQSSU
2244668
public static Bitmap KiMosaic(Bitmap b, int val)
{
if (b.Equals(null))
{
return null;
}
int w = b.Width;
int h = b.Height;
int stdR, stdG, stdB;
stdR = 0;
stdG = 0;
stdB = 0;
BitmapData srcData = b.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
byte* p = (byte*)srcData.Scan0.ToPointer();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
if (y % val == 0)
{
if (x % val == 0)
{
stdR = p[2]; stdG = p[1]; stdB = p[0];
}
else
{
p[0] = (byte)stdB;
p[1] = (byte)stdG;
p[2] = (byte)stdR;
}
}
else
{
// 复制上一行
byte * pTemp = p - srcData.Stride;
p[0] = (byte)pTemp[0];
p[1] = (byte)pTemp[1];
p[2] = (byte)pTemp[2];
}
p += 3;
} // end of x
p += srcData.Stride - w * 3;
} // end of y
b.UnlockBits(srcData);
}
return b;
}
先上原图:
![](http://hi.csdn.net/attachment/201003/9/82054_1268122561n1fa.jpg)
再上效果图
![](http://hi.csdn.net/attachment/201003/9/82054_1268122564SNuL.jpg)
相关文章推荐
- 网站中的缩略图是如何生成的?(C#处理图像)
- C#GDI+图像处理
- C# 常见图像处理效果
- C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)
- asp.net(C#)利用QRCode生成二维码(续)-在二维码图片中心加Logo或图像
- 黄聪:C#图片处理封装类(裁剪、缩放、清晰度、加水印、生成缩略图)有示例(转)
- C# 自己实现的一套ORM程序附带实体生成工具
- Win8Metro(C#)数字图像处理--2.31灰度拉伸算法
- C#用一般处理程序ashx生成、传递数据
- Win8 Metro(C#)数字图像处理--2.40二值图像轮廓提取算法
- c#图像处理入门(-bitmap类和图像像素值获取方法)
- C#图像处理(二值化,灰阶)
- php图形图像处理之生成验证码
- 图像处理之基础---滤波器之高斯低通滤波器的高斯模板生成c实现
- C#处理数码相片之马赛克的实现
- C#对图片进行马赛克处理可控制模糊程度的实现代码
- Win8 Metro(C#)数字图像处理--2.47人脸红眼去除算法
- c# 中图像的简单二值化处理
- Win8Metro(C#)数字图像处理--2.6图像对比度调整
- Win8Metro(C#)数字图像处理--2.12Sobel边缘检测