10.4 應用實例
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方 法即可。
10.5 本章小結
本章學習了ASP.NET網站中圖形繪制的知識,重點在於Graphics對象的使用,由基本圖形 進而擴展到復雜圖形的繪制,最後通過幾個實際應用來加深理解。
當然,圖形操作最適合於Windows應用程序,由於System.Drawing是.NET基類庫的一部分 ,所以本章內容在Windows應用程序中仍可以適用。