随心所欲产生图案(.Net)

来源:互联网 发布:java百度地图开发 编辑:程序博客网 时间:2024/04/30 15:30
Christoph Wille
Translated by: Jacky Chen
First published: 2000/07/28

要是没有外部的元件支援,有一些东西是 ASP 无法办到的,也就是动态产生图案 - 不管是图表、横幅广告、或是简单的图形计数器。幸运的是,这在 ASP.NET 中已经改变了 - 使用内建的方法,图案可以动态产生以及能够用最大限度的组态设定能力传送到 client 端,且很容易办到。

使用本文章的原始程式码必须在 Webserver 安装 Microsoft .NET Framework SDK。同时我也假设读者对 C# 程式有一定程度的认识。

产生图案

在还没感受到 ASP.NET 庞大压力下,我做了一个较乏味简单的指令行程式,然後使用这个原始程式码作为我们 ASP.NET script 的基础。所不同的是这个指令行会将图案储存为一档案,而 ASP.NET script 将他送到 client 端。

现在,我们的范例程式做了什麽?就像一般常见的,一开始我们使用一般喜欢用的 "Hello World" 程式,文字会输出成一图案档,然後图案会依据目前所选定的字型以及字型大小,产生同样大小的 "Hello World" 文字(因此,要产生特大的图像就无法计算)

 

下面的 Script (pagecounter.cs) 是典型简单的指令行程式: 忽略包裹在周围的 class , 只有函式 Main执行时会被呼叫,这也就是我们产生图案所在的程式。

using System;using System.IO;using System.Drawing;using System.Drawing.Imaging;public class CTestBitmapFunctionality{public static void Main(){Bitmap newBitmap = null;Graphics g = null ;try { Font fontCounter = new Font("Lucida Sans Unicode", 12); // calculate size of the string. newBitmap = new Bitmap(1,1,PixelFormat.Format32bppARGB); g = Graphics.FromImage(newBitmap); SizeF stringSize = g.MeasureString("Hello World", fontCounter); int nWidth = (int)stringSize.Width; int nHeight = (int)stringSize.Height; g.Dispose(); newBitmap.Dispose();  newBitmap = new Bitmap(nWidth,nHeight,PixelFormat.Format32bppARGB); g = Graphics.FromImage(newBitmap); g.FillRectangle(new SolidBrush(Color.White),  new Rectangle(0,0,nWidth,nHeight)); g.DrawString("Hello World", fontCounter, new SolidBrush(Color.Black), 0, 0); newBitmap.Save("c://test.png", ImageFormat.PNG);} catch (Exception e){ Console.WriteLine(e.ToString());}finally { if (null != g) g.Dispose(); if (null != newBitmap) newBitmap.Dispose();}}}

这程式做了什麽?不管怎样,结果图案 test.png 会储存在 drive c:

图案如何产生?为了解原因,我们必须详细来看一下原始码。首先,图案大小必须是和要呈现的文字字型 "Hello World" 大小一样,因此,我会先计算文字大小,同时为达目的,我使用一个 size 1 x 1 的仿制图案,当我计算完成,我抓取图案然後产生一适当的大小图案。

原始码中有趣的一点是 Graphics 物件。当我要产生图像为何需要这物件呢? 理由是这是我要画进去的图案情境 (context) - 我可以在萤幕、印表机以及记忆体使用图案情境 - 正确来说就是 Bitmap。图案情境允许我在任何设备执行绘图操作 (既时是虚拟的)。

使用 DrawString,我现在可以根据白色背景 (使用 FillRectangle 产生) 的长方形规格输出文字 "Hello World"。图案完成了,我必须把它存到磁碟中。曾经有过自己设计过图案档格式都知道这是一件困难的事,使用 GDI+ (Graphics Device Interface) 就不是如此 - 我们只要使用一简单的命令就行了:

newBitmap.Save("c://test.png", ImageFormat.PNG);

就这样了! 只要将 ImageFormat.PNG 交换成 ImageFormat.JPEG,你就能有 jpeg 的档案。简单的使用图案,这就是我们一直想要的。

现在只是有个例外处理有待解释:一些函式会造成例外(例如,没有足够的记忆体来产生图像)。好的程式设计者必须能够自行清除,我必须处理释放 GraphicsBitmap - 而这也就是我在 finally 区块所做的 (因为他总是会被呼叫)。而在 finally 之後程式结束。

理论上来说,这个程式可以运作,但仅在原始码中,要让它实际来执行,必须先经过编译:

csc /R:System.DLL /R:System.Drawing.DLL pagecounter.cs

这样我们可以产生一 .EXE 档 pagecounter.exe。注意:这个档案在系统安装 Microsoft .NET framework 後才能执行喔!

现在 web server 上的工作

当作指令行应用程式执行起来相当棒,但如果作为 ASP.NET script 就必须使用一些小技巧:

  • 可选择的文字 (例如,计数器) 
  • 可选择的文字颜色
  • 可选择的背景颜色
  • 可选择的字型
  • 可选择的字型大小

如果有人感到这有点困难的话,你可以先看一下这个图案的 ASP.NET script 档案 (pagecounter.aspx) 的原始码 原始码。 我所必须做的是加入一些错误处理程式码来检查传送的验证参数。这可说是必须改变的最大部分。

另外必须做的是将图案送到 client 端,而不是将它写入成为一个档案。这个新部分如下:

MemoryStream tempStream = new MemoryStream();newBitmap.Save(tempStream,ImageFormat.PNG);Response.ClearContent();Response.ContentType = "image/png";Response.BinaryWrite(tempStream.ToArray());Response.End();

我只是将图案放入记忆体缓冲区,然後传送到这个熟悉的函式 BinaryWrite 是为位元组,同时:我需要这个函式 ClearContent,因为在这 Script 的最上部分有 Import 指令会送出空白列到 client 端,使得 PNG 图档无效。

如果你有仔细看一下 原始码 ,将会注意到我已经传送所有可选择的参数作为 querystring 参数。这样参数可能太长,因此向我这样的懒人,我自己建构了一个看起来舒适一点的表单 (form),这样我就能测试各种不同的值


〔注〕这张图案原先文字是德文,我在自己机器上测试将文字转成中文,因此,下载原始档是使用德文,你必须自己改成中文字。

这个 ASP.NET page (pagecountertest.aspx) 更棒的是我可以在同一个网页获得图案。这个 form 的 原始码 已经包含许多 server 端的 ASP.NET 控制项 (controls)。 这意味着可作为将来文章中的开胃菜,在 ASP.NET 架构中对於 form 的处理以及验证,会有详尽说明。

结论

在这篇文章中我们以飞速来看图案程式的一些特徵。对於我们的网站计划, ASP.NET 架构中现在能提供 web page 程式设计者对於 Windows 图案程式设计完整的使用操作。现在我们可以将 " 办不到 " 这句话抛之脑後了。

下载程式码

按这里,开始下载。

原创粉丝点击