C#-GDI+编程之基础篇

C# GDI+编程之基本篇 一、有关GDI+ 从本质上来看,GDI+为开发者提供了一组实现与多种设备(例如监视器,打印机及其他具有图形化能力但不及波及这些图形细节的设备)进行交互的库函数GDI+的本质在于,它可以替代开发人员实现与例如显示屏及其他外设的交互;而从开发者角度来看,要实现与这些设备的直接交互却是一项艰巨的任务下图1展示了GDI+在开发人员与上述设备之间起着重要的中介作用其中,GDI+为我们“包办”了几乎一切—从把一种简朴的字符串“HelloWorld”打印到控制台到绘制直线,矩形甚至是打印一种完整的表单等 图1.GDI+担当着重要的中介作用 那么,GDI+是如何工作的呢?为了弄清这个问题,让我们来分析一种示例—绘制一条线段实质上,一条线段就是一种从一种开始位置(X0,Y0)到一种结束位置(Xn,Yn)的一系列像素点的集合为了画出这样的一条线段,设备(在本例中指显示屏)需要懂得相应的设备坐标或物理坐标然而,开发人员不是直接告诉该设备,而是调用GDI+的drawLine()措施,然后,由GDI+在内存(即“视频内存”)中绘制一条从点A到点B的直线GDI+读取点A和点B的位置,然后把它们转换成一种像素序列,并且指令监视器显示该像素序列。
简言之,GDI+把设备独立的调用转换成了一种设备可理解的形式;或者实现相反方向的转换 至此,我们已经简朴理解了GDI+的工作机理目前,让我们开始探讨如何实现某些基本的图像操作 二、图像操作—缩略图,缩放与保存 在本文示例中,我们将实现如下的任务: 1. 创立缩略图 2. 缩放一种加载的图像 3. 保存一种操作中的图像 a) 创立缩略图 缩略图是图像的浓缩版本典型状况下,一幅缩略图图像的尺寸为80×200像素在GDI+中,一种图像的缩略图可以通过使用Image类的GetThumbnailImage()措施来创立其函数原型如下: public Image GetThumbnailImage (int thumbWidth,int thumbHeight,GetThumbnailImageAbort callback,IntPtr callbackData)第一种参数相应于缩略图的宽度;第二个参数相应于生成的缩略图的高度;第三个参数是一种Image.GetThumbnailImageAbort委托在 GDI+ 1.0 版中不使用此委托即便如此,也必须创立一种委托并在该参数中传递对此委托的引用。
第四个参数同样没有使用,但是也需要提供以实现兼容性注意,第四个参数必须为IntPtr.Zero 如果前两个参数(也就是宽度和高度)都为0的话,那么,GDI+返回一种嵌入式缩略图否则,使用系统定义尺寸创立该缩略图例如,如果img是一种图像类的实例,并且使用的宽度和高度都是系统定义的,创立一种缩略图的语句应当如下所示: Image thumbNailImage = img.GetThumbnailImage(0,0,tnCallBack,IntPtr.Zero);在此,thumbNailImage涉及返回的缩略图,而tnCallback是一种相应于Image.GetThumbnailImageAbort的函数,其定义如下: //必须调用它,但是没有使用 style='font-size:10.0pt;font-family:Verdana'>publicbool tnCallbackMethod()...{return false;}b) 缩放一种加载的图像 缩放是放大或缩小一种图像的过程—通过在图像尺寸上乘以缩放因子实现其中,缩放因子=盼望的图像尺寸/目前图像尺寸例如,要把一种图像放大200%,则目前尺寸必须乘以200%(200%=200/100=2);为了缩小一种图像到25%,则目前尺寸必须乘以25%或0.25(25/100=0.25倍)。
c) 保存图像 保存操作是图像操作中的核心操作之一在保存一种图像时,图像相应的类型信息也必须进行保存;也就是说,该图像的扩展名在这一过程中具有重要角色每一种类型相应于一种特定的格式实质上,在保存一种图像时,根据该格式输出数据是非常必要的然而,借助于GDI+ API的优势,一种对Image类的Save()措施的简朴调用就可以把相应的写数据操作中所有细节省略掉这个措施使用两个参数—被保存的图像的名字和待保存图像的格式该格式可以通过ImageFormat类提供的类型来指定下列表格指定了GDI+支持的多种图像格式 属性 描述 Bmp 指定BMP格式 Emf 指定EMF(增强的元文献格式) Exif 指定EXIF格式 Gif 指定GIF格式 Guid 指定一种GUID构造,用于描述ImageFormatobject Icon 指定Windows图标格式 Jpeg 指定JPEG格式。
MemoryBmp 指定内存位图格式 Png 指定PNG格式 Tiff 指定TIFF格式 Wmf 指定WMF(Windows元文献格式)其中,Emf和Wmf是特定于Windows系统的 假定你想使用名字“checker.gif”保存一种图像,那么,相应的实现语句将是: curImage.Save(“checker.gif”,ImageFormat.Gif); 这里,curImage相应于Image类的实例 在下一节中,我将对前面开发的这个应用程序进行扩展 #p#三、实际开发中的图像操作 下面,我们来讨论实际中的使用状况我将在本文示例应用程序中添加下列功能: 1. 以顾客指定的格式保存图像2. 根据从菜单下选择的比例放大图像3. 创立一种加载图像的略缩图 相应的菜单操作如下所示: mnuSave—文献菜单下保存图像的子菜单 mnu200Zoom—放大图像200% mnuThumbNail—创立图像的一种略缩图 下面是解决菜单项mnuSave的Click事件相应的措施: private void mnuSave_Click(object sender,System.EventArgs e)...{//如果图像已经创立 if(curImage == null)return;//调用SaveFileDialog对话框 SaveFileDialog saveDlg = new SaveFileDialog();saveDlg.Title = "Save Image As";saveDlg.OverwritePrompt = true;saveDlg.CheckPathExists = true;saveDlg.Filter ="Bitmap File(*.bmp)|*.bmp|" +"Gif File(*.gif)|*.gif|" +"JPEG File(*.jpg)|*.jpg|" +"PNG File(*.png)|*.png" ;saveDlg.ShowHelp = true;//如果选择,则进行保存 if(saveDlg.ShowDialog() == DialogResult.OK)...{//得到顾客选择的文献名 string fileName = saveDlg.FileName;//得到文献扩展名 string strFilExtn =fileName.Remove(0,fileName.Length - 3);//保存文献 switch(strFilExtn)...{case "bmp":curImage.Save(fileName, ImageFormat.Bmp);break;case "jpg":curImage.Save(fileName, ImageFormat.Jpeg);break;case "gif":curImage.Save(fileName, ImageFormat.Gif);break;case "tif":curImage.Save(fileName, ImageFormat.Tiff);break;case "png":curImage.Save(fileName, ImageFormat.Png);break;default:break;}}}一方面,以可接受的扩展名显示这个保存对话框。
然后,由从该对话框返回的文献名检索相应的扩展名最后,根据该扩展名,使用相应的图像格式参数调用Save()措施 接下来,我们分析菜单项mnu200Zoom相应的解决器一方面,让我们在应用程序级添加下列以粗体显示的一行:private double curZoom=1.0;private Image curImage=null;//用于存储目前图像 private int i = 0;//用于把屏幕重画操作与缩略图绘制部分区别开来 然后,必须对mnuLoad解决代码作少量调节,如下所示:private void mnuLoad_Click(object sender,System.EventArgs e)...{//创立OpenFileDialog OpenFileDialog opnDlg = new OpenFileDialog();//设立一种图像类型过滤器 opnDlg.Filter ="All Image files|*.bmp;*.gif;*.jpg;*.ico;"+"*.emf;,*.wmf|Bitmap Files(*.bmp;*.gif;*.jpg;"+"*.ico)|*.bmp;*.gif;*.jpg;*.ico|"+"Meta Files(*.emf;*.wmf;*.png)|*.emf;*.wmf;*.png";opnDlg.Title = "打开图像文献";opnDlg.ShowHelp = true;//如果OK,选择它 if(opnDlg.ShowDialog() == DialogResult.OK)...{//读取目前选择的文献名 curFileName = opnDlg.FileName;//使用Image.FromFile创立图像对象 try...{curImage = Image.FromFile(curFileName);}catch(Exception exp)...{MessageBox.Show(exp.Message);}}//变化AutoScrollMinSize属性 this.AutoScrollMinSize = new Size((int)(curImage.Width * curZoom),(int)(curImage.Height * curZoom));i++;//重新绘制表单 Invalidate();}#p#注意,在此新添加的代码分别在本来的图像宽度和高度上乘以放大因子以生成一种放大的图像。
然后,必须相应地修改paint事件的解决器如下所示:private void Form1_Paint(object sender, PaintEventArgs e)...{if (curImage != null && i==0)...{Graphics g = this.CreateGraphics();g.DrawImage(curImage, new Rectangle(AutoScrollPosition.X,AutoScrollPosition.Y ,(int)(this.ClientRectangle.Width * curZoom),(int)(ClientRectangle.Height * curZoom)));}}该图像应当有根据放大因子的相应的高度和宽度下面,我们来看一下mnu200Zoom菜单项相应的事件解决器: private void mnu200_Click(object sender,System.EventArgs e)...{if(curImage != null)...{curZoom = (double)200/100;i++;Invalidate();}}最后,我们来看一下mnuThumbNail菜单项相应的事件解决器: 1private void mnuThumbnail_Click(object sender, EventArgs e) 2...{ 3if(curImage != null) 4...{ 5i++; 6//回调 7Image.GetThumbnailImageAbort tnCallBack = 8new Image.GetThumbnailImageAbort(tnCallbackMethod); 9//得到缩略图图像 10Image thumbNailImage = curImage.GetThumbnailImage11(100, 100, tnCallBack, IntPtr.Zero);12//创立一种Graphics对象 13Graphics tmpg = this.CreateGraphics();14tmpg.Clear(this.BackColor);15//画缩略图图像 16tmpg.DrawImage(thumbNailImage, 10, 10, thumbNailImage.Width, thumbNailImage.Height);17//释放掉Graphics对象 18tmpg.Dispose();19}2021}22在此,我们一方面创立一种GetThumbnailImageAbort类型的变量并且赋给它值tnCallbackMethod()—这是通过传递给该措施GetThumbnailImageAbort实现的。
然后,它创立一种新的Image类的实例以存储GetThumbnailImage措施返回的图像—此后,这个措施将用于把缩略图绘制到屏幕上 四、小结 在本文中,我仅讨论了.NET C#环境下有关GDI+编程的某些基本的实用操作片断在后来的文章中,我们将逐渐展开对.NET GDI+编程高档特性的探讨注】 ①本文源码在Windows XP Professonal+VS环境下调试通过;②本示例中私有变量的i的引入仅为了把屏幕重绘与缩略图绘制区别开来,读者可考虑其他更巧妙的措施; ③图像重绘及滚动过程中浮现屏幕抖动现象,读者可结合有关图像绘制双缓冲技术予以改善。