运用Visual C#完成基本数字图像处理
更新时间:2023-11-13 08:26:01 阅读量: 教育文库 文档下载
运用Visual C#完成基本数字图像处理
引言:
微软的新的.NET平台为开发者带来了许多新的诸如GDI+、Globalization之类的编程机制,同时还发明了一门全新的类似Java的编程语言-C#。对于这些新知识,我们应尽快了解、掌握并试图运用到实践项目中去,而通过实例学习的方法无疑是一个非常有效的途径。本文就通过一个简单的实例,向大家展示了在Visual C#中如何运用GDI+和Unsafe代码类等技术以实现简单的数字图像处理。
一.概述:
本文的实例是一个数字图像处理的应用程序,它完成的功能包括对图像颜色的翻转、对图像进行灰度处理和对图像进行增亮处理。该程序对图像进行处理部分的代码包含在一个专门的Filters类里面,通过调用该类里的静态成员函数,我们就可以实现相应的图像处理功能了。为实现图像处理,我们要对图像进行逐个象素处理。我们知道图像是由一个个的象素点组成的,对一幅图像的每个象素进行了相应的处理,最后整个图像也就处理好了。在这个过程中,我们只需对每个象素点进行相应的处理,在处理过程中却不需要考虑周围象素点对其的影响,所以相对来说程序的实现就变得简单多了。
由于GDI+中的BitmapData类不提供对图像内部数据的直接访问的方法,我们唯一的办法就是使用指针来获得图像的内部数据,这时我们就得运用unsafe这个关键字来指明函数中访问图像内部数据的代码块了。在程序中,我还运用了打开文件和保存文件等选项,以使我们的辛勤劳动不付之东流。
二.程序的实现:
1.打开Visual Studio.net,新建一个Visual C#的项目,在模板中选择\应用程序\即可,项目名称可自定(这里为ImageProcessor)。
2.为使窗体能显示图像,我们需要重载窗体的OnPaint()事件函数,在该函数中我们将一个图像绘制在程序的主窗体上,为了使窗体能显示不同尺寸大小的图像,我们还将窗体的AutoScroll属性设置为true。这样,根据图像的尺寸,窗体两边就会出现相应的滚动条。该函数的实现如下:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_Bitmap, new Rectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y, (int)(m_Bitmap.Width), (int)(m_Bitmap.Height))); }
3.给主窗体添加一个主菜单,该主菜单完成了一些基本的操作,包括\打开文件\、\保存文件\、\退出\、\翻转操作\、\灰度操作\、\增亮操作\等。前面三个操作完成图像文件的打开和保存以及程序的退出功能,相应的事件处理函数如下:
private void menuItemOpen_Click(object sender, System.EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = \文件(*.bmp)|*.bmp| Jpeg文件(*.jpg)|*.jpg| 所有合适文件(*.bmp/*.jpg)|*.bmp/*.jpg\ openFileDialog.FilterIndex = 2 ; openFileDialog.RestoreDirectory = true ; if(DialogResult.OK == openFileDialog.ShowDialog()) { m_Bitmap = (Bitmap)Bitmap.FromFile(openFileDialog.FileName, false); this.AutoScroll = true; this.AutoScrollMinSize=new Size ((int)(m_Bitmap.Width),(int) m_Bitmap.Height)); } this.Invalidate(); }
其中,m_Bitmap为主窗体类的一个数据成员,声明为private System.Drawing.Bitmap m_Bitmap;(注:因为程序中用到了相关的类,所以在程序文件的开始处应添加using System.Drawing.Imaging;)同时,在该类的构造函数中,我们必须先给它new一个Bitmap对象:m_Bitmap = new Bitmap(2,2);上述代码中的this.Invalidate();完成主窗体的重绘工作,它调用了主窗体的OnPaint()函数,结果就将打开的图像文件显示在主窗体上。
private void menuItemSave_Click(object sender, System.EventArgs e) { SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = \文件(*.bmp)|*.bmp| Jpeg文件(*.jpg)|*.jpg| 所有合适文件(*.bmp/*.jpg)|*.bmp/*.jpg\ } saveFileDialog.FilterIndex = 1 ; saveFileDialog.RestoreDirectory = true ; if(DialogResult.OK == saveFileDialog.ShowDialog()) { } m_Bitmap.Save(saveFileDialog.FileName);
其中m_Bitmap.Save(saveFileDialog.FileName);一句完成了图像文件的保存,正是运用了GDI+的强大功能,我们只需这么一条简单的语句就完成了以前很大工作量的任务,所以合理运用.NET中的新机制一定会大大简化我们的工作的。
private void menuItemExit_Click(object sender, System.EventArgs e) { } this.Close();
接下来,三个主要操作的事件处理函数如下:
private void menuItemInvert_Click(object sender, System.EventArgs e) { if(Filters.Invert(m_Bitmap)) } this.Invalidate(); private void menuItemGray_Click(object sender, System.EventArgs e) { if(Filters.Gray(m_Bitmap)) } this.Invalidate(); private void menuItemBright_Click(object sender, System.EventArgs e) { Parameter dlg = new Parameter(); dlg.nValue = 0; if (DialogResult.OK == dlg.ShowDialog())
} { } if(Filters.Brightness(m_Bitmap, dlg.nValue)) this.Invalidate();
三个函数中分别调用了相应的图像处理函数Invert()、Gray()、Brightness()等三个函数。这三个函数Filters类中的三个类型为public的静态函数(含有static关键字),它们的返回值类型均是bool型的,根据返回值我们可以决定是否进行主窗体的重绘工作。
Invert()、Gray()、Brightness()等三个函数均包含在Filters类里面,Invert()函数的算法如下:
public static bool Invert(Bitmap b) { BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe { } } byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; for(int y=0;y 该函数以及后面的函数的参数都是Bitmap类型的,它们传值的对象就是程序中所打开的图像文件了。该函数中的BitmapData类型的bmData包含了图像文件的内部信息,bmData的Stride属性指明了一条线的宽度,而它的Scan0属性则是指向图像内部信息的指针。本函数完成的功能是图像颜色的翻转,实现的方法即用255减去图像中的每个象素点的值,并将所得值设置为原象素点处的值,对每个象素点进行如此的操作,只到整幅图像都处理完毕。函数中的unsafe代码块是整个函数的主体部 分,首先我们取得图像内部数据的指针,然后设置好偏移量,同时设置nWidth为b.Width*3,因为每个象素点包含了三种颜色成分,对每个象素点进行处理时便要进行三次处理。接下来运用两个嵌套的for循环完成对每个象素点的处理,处理的核心便是一句:p[0] = (byte)(255-p[0]);。在unsafe代码块后,便可运用b.UnlockBits(bmData)进行图像资源的释放。函数执行成功,最后返回true值。注:由于是要编译不安全代码,所以得将项目属性页中的\允许不安全代码块\属性设置为true,图示如下: 该函数实现的程序效果如下: (处理前) (处理后) Gray()函数的算法如下: public static bool Gray(Bitmap b) { BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe } { { for(int x=0; x < b.Width; ++x ) { blue = p[0]; green = p[1]; red = p[2]; p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue); p += 3; } p += nOffset; } } b.UnlockBits(bmData); return true; byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; byte red, green, blue; for(int y=0;y
正在阅读:
武汉和长沙城市定位、城市规模和城市形态的比较 - 图文12-31
河南省鹤壁市淇滨高级中学化学提高题专题复习第五章 抛体运动 练习题含答案解析05-04
大四入党积极分子思想汇报格式及范文09-08
10.1《浮力》导学案05-20
思想汇报201602-24
2016年警察思想汇报02-24
2016年学习科学发展观的思想汇报02-24
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- C#
- 图像处理
- 运用
- 完成
- 基本
- 数字
- Visual
- 六年级数学分数四则混合运算练习题(1)
- 文书发展
- 沪教版初中数学中考总复习(知识点考点梳理、重点题型分类巩固练习)(基础版)(家教、补习、复习用)
- 换热器原理与设计(答案)
- 2013年高职院校单独招生告家长书
- 《大学英语精读》(预备级)教学大纲
- 五病调离制度及消毒记录本
- 2017美国留学招生趋势大解读揭秘提升被名校录取几率的捷径
- 物化03级本科试题(下)
- 江苏专转本英语2007-2011真题及答案详解
- 线性代数习题答案(复旦版周勇 - 朱砾)
- 河北大学 - 普通物理练习题
- 对联和碑文
- 建筑施工现场常用机械设备用电功率表
- 达克罗技术
- 采油地质工中级理论知识题-答案(1)
- 鄂教版一下品德
- 农村建房预防地质灾害知识
- TD-SCDMA试题
- 管道工习题及答案