扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:王凯明 来源:论坛 2007年11月14日
关键字:
private void menuItemOpen_Click(object sender, System.EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Bitmap文件(*.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 = "Bitmap文件(*.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<b.Height;++y) { for(int x=0; x < nWidth; ++x ) { p[0] = (byte)(255-p[0]); ++p; } p += nOffset; } } b.UnlockBits(bmData); return true; } |
该函数以及后面的函数的参数都是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,图示如下:
该函数实现的程序效果如下:
(处理前)
(处理后)
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者