前言: 本文章抄袭自本人刚刚买的《ASP.NET 3.5从入门到精通》这本书,此书介绍在 http://www.china-pub.com/44991 ,本文章95%与此书的内容完全一样,另5%是我改正一些失误以后加上去的,该书原示例代码只能运行在IE核心的浏览器上,非IE核心浏览器上运行会出现些显示问题,本人更改了其中的一些代码。本文章经历昨晚本人五个小时的手打而成(且还未打完,下班回去继续打,想不到我的打字速度退化得这么快,郁闷!!!),俗话说:好记性不如烂笔头,把书的内容手打出来,对手,对脑,都有好处!!!
10.4.1 饼图
统计图是信息管理系统常用的功能,常用的有饼图、柱形图、拆线图等。饼图用来表示各部分比例,柱形图用来表示各部分的比较,拆线图用来表示发展趋势,另外还有其他一些具有特殊功能的图示。本小节将以二维饼图为例说明通过.NET GDI+来绘制统计图的原理。
本例实现效果很简单,即根据给予的一组数据计算出各个数据项的比例,并分别用不同颜色表示,组成一个圆饼,如下图所示:
用户可以使用FillPie来绘制饼块,多个饼块拼接在一起就形成了圆饼效果。其基本算法就是每个部分角度的计算,在总共360°的条件下,每个部分会占多少度。为了方便起见,本例的数据源采用数组,在实例应用过程中,数组数据可以来自数据库,具体代码如下:
int[] arr = {100,35,115,125,75,120 }; // 原书中没有这句,表示不同的颜色 Color[] colors = { Color.BlueViolet,Color.Yellow,Color.Green,Color.Gray,Color.Blue,Color.Purple}; Bitmap bmp = new Bitmap(400,400); // 创建一个图像 Graphics g = Graphics.FromImage(bmp); // 创建Graphics 对象 g.Clear(Color.White); // 白色背景 g.DrawString("本书上半年销售情况", new Font("黑体",16), Brushes.Black, new PointF(5,5)); // 标题 float length = 200; float currentAngle = 0; // 当前饼块的角度 float totalAngle = 0; // 已画完的饼块的角度和 float totalValues = 0; // 所有值总和 // 所有值求和 foreach (int i in arr) { totalValues += i; } // 开始画饼块 for (int i = 0; i < arr.Length;i++ ) { currentAngle = arr[i] / totalValues * 360; // 计算当前饼块角度 g.FillPie(new SolidBrush(colors[i]), 100, 50, length, length, totalAngle, currentAngle); // 填充饼块 // 画饼块边界 g.DrawPie(Pens.Black, 100, 50, length, length, totalAngle, currentAngle); totalAngle += currentAngle; } // 原书示例代码中没有,没有这句则在非IE浏览器会出错 Response.ContentType = "image/GIF"; // 将图形加载到Response中 bmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); g.Dispose();
上面代码粘贴到Page_Load中,运行页面就可以看到效果中的样子。如果想在饼块的各个部分添加说明文字,可以使用DrawString绘制文字,或者在图的空白处显示图例说明,图例可以使用FillRectangle绘制矩形区域。
10.4.2 水印
在网络中发布资源时,比如图片,很多时候需要保护版权,即在图片上显示版权信息。要实现这样的效果,最简单有效的办法就是给图片添加水印(WaterMark),它和人民币中的水印原理一样,不容易涂改。通过制图软件一张一张地添加水印在技术上固然可行,但是工作量庞大,有时无法适应快速反应的要求,在实际操作中很少采用。在ASP.NET网站中,用户可以利用本小节的知识来实现自动添加水印。这里讲述两种水印:图像水印和文字水印。
图像水印就是在要保护的图片中加入另一个作为水印的图片,即两个图片合二为一,基基本原理就是将一个图片绘制到另一个图片当中,形成一个图片。比如有个风景图片,为了表示版权信息,用户希望在图片的右下角添加说明,如图:
在实现代码以前,用户需要先准备好一个作为水印的图片tg029.jpg,一张 需要添加水印的图片Element.jpg。下面的代码利用了Graphics的DrawImage方法将tg029.jpg绘制到Element.jpg中去。
string file = Server.MapPath("~/Element.jpg"); string mark = Server.MapPath("~/tg029.jpg"); // 需要添加水印的图像 System.Drawing.Image img = System.Drawing.Image.FromFile(file); // 水印图像 System.Drawing.Image imgMark = System.Drawing.Image.FromFile(mark); // 创建Graphics对象 Graphics g = Graphics.FromImage(img); // 将水印图像绘制到目标图像中去 g.DrawImage(imgMark,img.Width-imgMark.Width,img.Height-imgMark.Height); // 原书示例代码中没有,没有这句则在非IE浏览器会出错 Response.ContentType = "image/JPEG"; //将图像加载到Response中 img.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg); g.Dispose();
其实,添加水印并没有破坏Element.jpg原图,只是在内存中形成新的图像对象,然后存入响应流中,并发送到客户端显示。这样做即保护了版权,又不损坏原图。
有些时候人们喜欢用图片上加文字的方式来保护版权,参考如下图:
这里可以用DrawString方法来向图片绘制文本。为了使文字不至于影响图片效果,可以将其颜色设置为谈灰色,并适当调整透明度,参考代码如下:
string file = Server.MapPath("~/Element.jpg"); System.Drawing.Image img = System.Drawing.Image.FromFile(file); // 写文字的笔刷,透明度为100,淡灰色 Brush b = new SolidBrush(Color.FromArgb(100,Color.LightGray)); // 字体设置 FontFamily ff = new FontFamily("华文琥珀"); Font f = new Font(ff, 100, FontStyle.Bold); // 文字区域左上角坐标 float x = 50; float y = 50; Graphics g = Graphics.FromImage(img); //设置Graphics对象 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; // 文字 g.DrawString("牛腩制作",f,b,new PointF(x,y)); // 原书示例代码中没有,没有这句则在非IE浏览器会出错 Response.ContentType = "image/JPEG"; //将图像加载到Response中 img.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); g.Dispose();
如果是批量处理图片水印,则反复调用上述代码即可。当然,用户也可以设计出更美观的水印效果,并使用上述方法添加到图片中去。
10.4.3 缩略图
Web应用中最薄弱的环节就是传输,即速度问题。图片格式的数据往往比较大,所以网络中并不适合传输较大的图片。除了采用压缩格式(比如GIF,JPEG等)传输外,还可以使用缩略图的方式加快浏览速度,也可以节省页面空间。使用Image类中的GetThumbnailImage方法可以很方便地生成缩略图,如下面的代码示例:
// 取消操作回调 private bool ThumbnailCallback() { return false; } // 产生缩略图 private void Thumb(string imgPath, string thumbPath) { System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback); System.Drawing.Image img = System.Drawing.Image.FromFile(imgPath); // 通过文件构造 //生成缩略图 System.Drawing.Image myThumbnail = img.GetThumbnailImage(100,50,myCallback, IntPtr.Zero); myThumbnail.Save(thumbPath); // 保存缩略图 }
用户可以简单地写一个测试脚本:
Thumb(Server.MapPath("~/Element.jpg"), Server.MapPath("~/Element_small.jpg"));
程序运行后,即生成了100*100规格的缩略图。如果要批量生成缩略图,多次调用Thumb方法即可。
本章学习了ASP.NET网站中图形绘制的知识,重点在于Graphics对象的使用,由基本图形进而扩展到复杂图形的绘制,最后通过几个实际应用来加深理解。
当然,图形操作最适合于Windows应用程序,由于System.Drawing是.NET基类库的一部分,所以本章内容在Windows应用程序中仍可以适用。