C#图像处理.docx
- 文档编号:5743440
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:14
- 大小:31.72KB
C#图像处理.docx
《C#图像处理.docx》由会员分享,可在线阅读,更多相关《C#图像处理.docx(14页珍藏版)》请在冰豆网上搜索。
C#图像处理
一.Bitmap类
Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下:
1.GetPixel方法和SetPixel方法:
获取和设置一个图像的指定像素的颜色.
2.PixelFormat属性:
返回图像的像素格式.
3.Palette属性:
获取和设置图像所使用的颜色调色板.
4.HeightWidth属性:
返回图像的高度和宽度.
5.LockBits方法和UnlockBits方法:
分别锁定和解锁系统内存中的位图像素.在基于像素点的图像处理方法中使用LockBits和UnlockBits是一个很好的方式,这两种方法可以使我们指定像素的范围来控制位图的任意一部分,从而消除了通过循环对位图的像素逐个进行处理,每调用LockBits之后都应该调用一次UnlockBits.
二.BitmapData类
BitmapData对象指定了位图的属性
1.Height属性:
被锁定位图的高度.
2.Width属性:
被锁定位图的高度.
3.PixelFormat属性:
数据的实际像素格式.
4.Scan0属性:
被锁定数组的首字节地址,如果整个图像被锁定,则是图像的第一个字节地址.
5.Stride属性:
步幅,也称为扫描宽度.
如上图所示,数组的长度并不一定等于图像像素数组的长度,还有一部分未用区域,这涉及到位图的数据结构,系统要保证每行的字节数必须为4的倍数.
三.Graphics类
Graphics对象是GDI+的关键所在,许多对象都是由Graphics类表示的,该类定义了绘制和填充图形对象的方法和属性,一个应用程序只要需要进行绘制或着色,它就必须使用Graphics对象.
四.Image类
这个类提供了位图和元文件操作的函数.Image类被声明为abstract,也就是说Image类不能实例化对象,而只能做为一个基类.
1.FromFile方法:
它根据输入的文件名产生一个Image对象,它有两种函数形式:
publicstaticImageFromFile(stringfilename);
publicstaticImageFromFile(stringfilename,booluseEmbeddedColorManagement);
2.FromHBitmap方法:
它从一个windows句柄处创建一个bitmap对象,它也包括两种函数形式:
publicstaticbitmapfromhbitmap(intptrhbitmap);
publicstaticbitmapfromhbitmap(intptrhbitmap,intptrhpalette);
3.FromStream方法:
从一个数据流中创建一个image对象,它包含三种函数形式:
publicstaticimagefromstream(streamstream);
publicstaticimagefromstream(streamstream,booluseembeddedcolormanagement);
fromstream(streamstream,booluseembeddedcolormanagement,boolvalidateimagedata);
有了上面的了解,我们便可以开始利用C#做图像处理,下面介绍几种方法:
一.打开、保存、显示图像
privateBitmapsrcBitmap=null;
privateBitmapshowBitmap=null;
//打开文件
privatevoidmenuFileOpen_Click(objectsender,EventArgse)
{
OpenFileDialogopenFileDialog=newOpenFileDialog();
openFileDialog.Filter=@"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合适文件(*.bmp,*.jpg)|*.bmp;*.jpg";
openFileDialog.FilterIndex=3;
openFileDialog.RestoreDirectory=true;
if(DialogResult.OK==openFileDialog.ShowDialog())
{
srcBitmap=(Bitmap)Bitmap.FromFile(openFileDialog.FileName,false);
showBitmap=srcBitmap;
this.AutoScroll=true;
this.AutoScrollMinSize=newSize((int)(showBitmap.Width),(int)(showBitmap.Height));
this.Invalidate();
}
}
//保存图像文件
privatevoidmenuFileSave_Click(objectsender,EventArgse)
{
if(showBitmap!
=null)
{
SaveFileDialogsaveFileDialog=newSaveFileDialog();
saveFileDialog.Filter=@"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合适文件(*.bmp,*.jpg)|*.bmp;*.jpg";
saveFileDialog.FilterIndex=3;
saveFileDialog.RestoreDirectory=true;
if(DialogResult.OK==saveFileDialog.ShowDialog())
{
ImageFormatformat=ImageFormat.Jpeg;
switch(Path.GetExtension(saveFileDialog.FileName).ToLower())
{
case".jpg":
format=ImageFormat.Jpeg;
break;
case".bmp":
format=ImageFormat.Bmp;
break;
default:
MessageBox.Show(this,"Unsupportedimageformatwasspecified","Error",
MessageBoxButtons.OK,MessageBoxIcon.Error);
return;
}
try
{
showBitmap.Save(saveFileDialog.FileName,format);
}
catch(Exception)
{
MessageBox.Show(this,"Failedwritingimagefile","Error",
MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
}
}
//窗口重绘,在窗体上显示图像,重载Paint
privatevoidfrmMain_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
if(showBitmap!
=null)
{
Graphicsg=e.Graphics;
g.DrawImage(showBitmap,newRectangle(this.AutoScrollPosition.X,this.AutoScrollPosition.Y,
(int)(showBitmap.Width),(int)(showBitmap.Height)));
}
}
//灰度化
privatevoidmenu2Gray_Click(objectsender,EventArgse)
{
if(showBitmap==null)return;
showBitmap=RGB2Gray(showBitmap);//下面都以RGB2Gray为例
this.Invalidate();
}
二.提取像素法
这种方法简单易懂,但相当耗时,完全不可取.
publicstaticBitmapRGB2Gray(BitmapsrcBitmap)
{
ColorsrcColor;
intwide=srcBitmap.Width;
intheight=srcBitmap.Height;
for(inty=0;y for(intx=0;x { //获取像素的RGB颜色值 srcColor=srcBitmap.GetPixel(x,y); bytetemp=(byte)(srcColor.R*.299+srcColor.G*.587+srcColor.B*.114); //设置像素的RGB颜色值 srcBitmap.SetPixel(x,y,Color.FromArgb(temp,temp,temp)); } returnsrcBitmap; }//# 三.内存法 这是比较常用的方法 publicstaticBitmapRGB2Gray(BitmapsrcBitmap) { intwide=srcBitmap.Width; intheight=srcBitmap.Height; Rectanglerect=newRectangle(0,0,wide,height); //将Bitmap锁定到系统内存中,获得BitmapData BitmapDatasrcBmData=srcBitmap.LockBits(rect, ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); //创建Bitmap BitmapdstBitmap=CreateGrayscaleImage(wide,height);//这个函数在后面有定义 BitmapDatadstBmData=dstBitmap.LockBits(rect, ImageLockMode.ReadWrite,PixelFormat.Format8bppIndexed); //位图中第一个像素数据的地址。 它也可以看成是位图中的第一个扫描行 System.IntPtrsrcPtr=srcBmData.Scan0; System.IntPtrdstPtr=dstBmData.Scan0; //将Bitmap对象的信息存放到byte数组中 intsrc_bytes=srcBmData.Stride*height; byte[]srcValues=newbyte[src_bytes]; intdst_bytes=dstBmData.Stride*height; byte[]dstValues=newbyte[dst_bytes]; //复制GRB信息到byte数组 System.Runtime.InteropServices.Marshal.Copy(srcPtr,srcValues,0,src_bytes); System.Runtime.InteropServices.Marshal.Copy(dstPtr,dstValues,0,dst_bytes); //根据Y=0.299*R+0.114*G+0.587B,Y为亮度 for(inti=0;i for(intj=0;j { //只处理每行中图像像素数据,舍弃未用空间 //注意位图结构中RGB按BGR的顺序存储 intk=3*j; bytetemp=(byte)(srcValues[i*srcBmData.Stride+k+2]*.299 +srcValues[i*srcBmData.Stride+k+1]*.587+srcValues[i*srcBmData.Stride+k]*.114); dstValues[i*dstBmData.Stride+j]=temp; } //将更改过的byte[]拷贝到原位图 System.Runtime.InteropServices.Marshal.Copy(dstValues,0,dstPtr,dst_bytes); //解锁位图 srcBitmap.UnlockBits(srcBmData); dstBitmap.UnlockBits(dstBmData); returndstBitmap; }//# 四指针法 C/C++的习惯,不是C#的特点 publicstaticBitmapRGB2Gray(BitmapsrcBitmap) { intwide=srcBitmap.Width; intheight=srcBitmap.Height; Rectanglerect=newRectangle(0,0,wide,height); BitmapDatasrcBmData=srcBitmap.LockBits(rect, ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); BitmapdstBitmap=CreateGrayscaleImage(wide,height); BitmapDatadstBmData=dstBitmap.LockBits(rect, ImageLockMode.ReadWrite,PixelFormat.Format8bppIndexed); System.IntPtrsrcScan=srcBmData.Scan0; System.IntPtrdstScan=dstBmData.Scan0; Unsafe//启动不安全代码 { byte*srcP=(byte*)(void*)srcScan; byte*dstP=(byte*)(void*)dstScan; intsrcOffset=srcBmData.Stride-wide*3; intdstOffset=dstBmData.Stride-wide; bytered,green,blue; for(inty=0;y { for(intx=0;x { blue=srcP[0]; green=srcP[1]; red=srcP[2]; *dstP=(byte)(.299*red+.587*green+.114*blue); } srcP+=srcOffset; dstP+=dstOffset; } } srcBitmap.UnlockBits(srcBmData); dstBitmap.UnlockBits(dstBmData); returndstBitmap; }//# 五.矩阵法 并不是什么新方法,只是将图像数据分做R,G,B三个矩阵(二维数组)存储,类似MATLAB的习惯. publicstaticboolGetRGB(BitmapSource,outint[,]R,outint[,]G,outint[,]B) { try { intiWidth=Source.Width; intiHeight=Source.Height; Rectanglerect=newRectangle(0,0,iWidth,iHeight); System.Drawing.Imaging.BitmapDatabmpData=Source.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,Source.PixelFormat); IntPtriPtr=bmpData.Scan0; intiBytes=iWidth*iHeight*3; byte[]PixelValues=newbyte[iBytes]; System.Runtime.InteropServices.Marshal.Copy(iPtr,PixelValues,0,iBytes); Source.UnlockBits(bmpData); //注意这个地方图像的两维方向与数组两维的方向是转置的关系 R=newint[iHeight,iWidth]; G=newint[iHeight,iWidth]; B=newint[iHeight,iWidth]; intiPoint=0; for(inti=0;i { for(intj=0;j { //注意,Windows中三基色的排列顺序是BGR而不是RGB! B[i,j]=Convert.ToInt32(PixelValues[iPoint++]); G[i,j]=Convert.ToInt32(PixelValues[iPoint++]); R[i,j]=Convert.ToInt32(PixelValues[iPoint++]); } } returntrue; } catch(Exception) { R=null; G=null; B=null; returnfalse; } }//# publicstaticBitmapFromRGB(int[,]R,int[,]G,int[,]B) { intiWidth=G.GetLength (1); intiHeight=G.GetLength(0); BitmapResult=newBitmap(iWidth,iHeight,System.Drawing.Imaging.PixelFormat.Format24bppRgb); Rectanglerect=newRectangle(0,0,iWidth,iHeight); System.Drawing.Imaging.BitmapDatabmpData=Result.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,System.Drawing.Imaging.PixelFormat.Format24bppRgb); IntPtriPtr=bmpData.Scan0; intiStride=bmpData.Stride; intiBytes=iWidth*iHeight*3; byte[]PixelValues=newbyte[iBytes]; intiPoint=0; for(inti=0;i for(intj=0;j { intiG=G[i,j]; intiB=B[i,j]; intiR=R[i,j]; PixelValues[iPoint]=Convert.ToByte(iB); PixelValues[iPoint+1]=Convert.ToByte(iG); PixelValues[iPoint+2]=Convert.ToByte(iR); iPoint+=3; } System.Runtime.InteropServices.Marshal.Copy(PixelValues,0,iPtr,iBytes); Result.UnlockBits(bmpData); returnResult; }//# publicstaticboolGetGray(BitmapsrcBitmap,outbyte[,]gray) { BitmaptempBitmap; if(srcBitmap.PixelFormat! =PixelFormat.Format8bppIndexed) tempBitmap=ImageProcess.Image.Gray(srcBitmap); else tempBitmap=srcBitmap; intwide=tempBitmap.Width; intheight=tempBitmap.Height; gray=newbyte[height,wide]; BitmapDatagbmData=tempBitmap.LockBits(newRectangle(0,0,wide,height), ImageLockMode.ReadWrite,PixelFormat.Format8bppIndexed); System.IntPtrScanG=gbmData.Scan0; intgOffset=gbmData.Stride-wide; unsafe { byte*g=(byte*)(void*)ScanG; //foreachpixel for(inty=0;y { //foreachpixel for(intx=0;x { gray[y,x]=*g; } g+=gOffset; } } tempBitmap.UnlockBits(gbmData); returntrue; }//# publicstaticBitmapFromGray(byte[,]Gray) { intiWidth=Gray.GetLength (1); intiHeight=Gray.GetLength(0); BitmapdstBitmap=ImageProcess.Image.CreateGrayscaleImage(iWidth,iHeight); BitmapDatagbmData=dstBitmap.LockBits(newRectangle(0,0,iWidth,iH
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 图像 处理