C#利用GDI+畫圖的基礎(chǔ)實(shí)例教程
前言
最近做一個(gè)微信公眾號(hào)服務(wù),有一些簡單的圖片處理功能。主要就是用戶在頁面操作,前端做一些立刻顯示的效果,然后提交保存時(shí)后端真正修改原圖。
從程序設(shè)計(jì)的角度看,GDI包括兩部分:一部分是GDI對象,另一部分是GDI函數(shù)。GDI對象定義了GDI函數(shù)使用的工具和環(huán)境變量,而GDI函數(shù)使用GDI對象繪制各種圖形,在C#中,進(jìn)行圖形程序編寫時(shí)用到的是GDI+(Graphics Device Interface Plus圖形設(shè)備接口)版本,GDI+是GDI的進(jìn)一步擴(kuò)展,它使我們編程更加方便。
C#中的GDI+就相當(dāng)于java中的Swing控件,是編寫圖形界面必不可缺的一個(gè)接口。GDI+繪圖最大的方便得益于C#的可視化編程,所有的控件只需要自己Drag,然后Place,最后Cilck添加監(jiān)聽方法。真的是too young too simple。
我們的后端是 ASP.NET,也就是 C# 語言了,C# 本身處理圖片還是比較方便的,使用 GDI+ 就好,只需要添加 System.Drawing 引用,不需要任何第三方庫。于是最近也用到一些比較常用的 GDI+ 圖片處理方法,就整理一下做個(gè)記錄了。
這個(gè)題目大概會(huì)寫幾篇文章,第一篇先簡單介紹一下 GDI+ 的常用對象,以及一些使用時(shí)候的注意事項(xiàng),后面會(huì)挑一些項(xiàng)目中做過的比較有用的處理過程來介紹一下。
廢話不多說,開始進(jìn)入正題。
需要用到的類
使用 GDI+ 畫圖會(huì)用到的幾個(gè)常用的類有:Graphics、Bitmap、Image。
其中 Graphics 是畫板。這個(gè)類包含了許多畫圖的方法,包括畫圖片(DrawImage),畫線(DrawLine),畫圓(DrawEllipse、FillEllipse),寫字(DrawString)等等。簡單說使用這個(gè)類可以完成我們需要的大部分工作。
生成一個(gè) Graphics 對象需要用到 Image 或者 Bitmap。
PS: Winform 下可以直接從窗體或控件的事件中引用 Graphics 對象。
比如:
 private void Form1_Paint(object sender, PaintEventArgs e)
 {
  Graphics g = e.Graphics; // 創(chuàng)建畫板,這里的畫板是由Form提供的.
 }
不過本文討論的是其他場景,比如 ASP.NET MVC,或單純的控制臺(tái)程序。這些時(shí)候是沒有控件的,所以要用其他方法。
我一般用以下方法:
// // 摘要: // 從指定的 System.Drawing.Image 創(chuàng)建新的 System.Drawing.Graphics。 // // 參數(shù): // image: // 從中創(chuàng)建新 System.Drawing.Graphics 的 System.Drawing.Image。 // // 返回結(jié)果: // 此方法為指定的 System.Drawing.Image 返回一個(gè)新的 System.Drawing.Graphics。 // // 異常: // T:System.ArgumentNullException: // image 為 null。 // // T:System.Exception: // image 具有索引像素格式,或者格式未定義。 public static Graphics FromImage(Image image);
其中的參數(shù)可以傳入 Image 或 Bitmap,因?yàn)?Bitmap 是繼承自 Image 的。
如何創(chuàng)建畫板
如果是要對原圖進(jìn)行處理,比如旋轉(zhuǎn)圖片,添加文字等,可以直接通過原圖片獲得畫板對象。
Image img = Image.FromFile(imgPath); Graphics graphics = Graphics.FromImage(img);
如果是要畫一個(gè)新的圖,可以通過要保存的圖片寬、高生成畫板。
Bitmap bmp = new Bitmap(width, height); Graphics graph = Graphics.FromImage(bmp);
PS: Graphics 本身是沒有提供構(gòu)造函數(shù)來直接生成的。所以我們可以先創(chuàng)建一個(gè)需要保存圖片大小的 Bitmap 位圖對象,然后再獲得畫板對象。
如何保存畫好的圖片
通過調(diào)用 img.Save(savePath) 或者 bmp.Save(savePath) 即可保存對象。
PS: Bitmap 的 Save 方法是直接繼承自 Image 的。
GDI+ 的坐標(biāo)系
GDI+ 的坐標(biāo)系是個(gè)二維坐標(biāo)系,不過又有點(diǎn)不一樣,它的原點(diǎn)是在左上角的。如下圖:
使用 GDI+ 的一些注意事項(xiàng)
這里我忍不住要先吐槽一下,GDI+ 的報(bào)錯(cuò)信息不太友好啊。經(jīng)常只是返回一個(gè)“GDI+ 中發(fā)生一般性錯(cuò)誤?!?,不能快速地根據(jù)這個(gè)錯(cuò)誤提示定位問題。比如說沒有釋放圖片資源時(shí)想再次訪問資源會(huì)報(bào)這個(gè)錯(cuò)誤,想要保存圖片的文件夾不存在時(shí)也是提示這個(gè)錯(cuò)誤??床怀鰜韰^(qū)別……
1. 保存到相同路徑的文件時(shí)要先釋放圖片資源,否則會(huì)報(bào)錯(cuò)(GDI+中發(fā)生一般性錯(cuò)誤)
Image img = Image.FromFile(imgPath); Bitmap bmp = new Bitmap(img); Graphics graphics = Graphics.FromImage(bmp); ... // 對圖片進(jìn)行一些處理 img.Dispose(); // 釋放原圖資源 bmp.Save(imgPath); // 保存到原圖 graphics.Dispose(); // 圖片處理過程完成,剩余資源全部釋放 bmp.Dispose();
2. 使用完的資源記得要釋放??梢杂?try..catch..finally 或者 using 的方式,這樣即使遇到代碼運(yùn)行報(bào)錯(cuò)也能及時(shí)釋放資源,更加保險(xiǎn)。
try..catch...finally:把釋放資源的代碼寫到 finally 代碼段里。
Image img = Image.FromFile(imgPath);
Bitmap bmp = new Bitmap(img);
Graphics graphics = Graphics.FromImage(bmp);
try
{
 ...
}
catch (System.Exception ex)
{
 throw ex;
}
finally
{
 graphics.Dispose();
 bmp.Dispose();
 img.Dispose();
}
using:使用 using 語句創(chuàng)建的資源會(huì)在離開 using 代碼段時(shí)自動(dòng)釋放該資源。
/// <summary>
/// 縮放圖像
/// </summary>
/// <param name="originalImagePath">原圖路徑</param>
/// <param name="destWidth">目標(biāo)圖寬度</param>
/// <param name="destHeight">目標(biāo)圖高度</param>
/// <returns></returns>
public Bitmap GetThumbnail(string originalImagePath, int destWidth, int destHeight)
{
 using (Image imgSource = Image.FromFile(originalImagePath))
 {
  return GetThumbnail(imgSource, destWidth, destHeight);
 }
}
3. 要保存圖片的文件夾一定要是已經(jīng)存在的,否則會(huì)報(bào)錯(cuò)(GDI+中發(fā)生一般性錯(cuò)誤)
eg:假設(shè)圖片要保存到 D:\test\output.png
 string directory = @"D:\test\";
 string fileName = "output.png";
 // 檢查文件夾是否存在,不存在則先創(chuàng)建
 if (!Directory.Exists(directory))
 {
  Directory.CreateDirectory(directory);
 }
 bmp.Save(directory + fileName);
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對我們的支持。
上一篇:winform實(shí)現(xiàn)可拖動(dòng)的自定義Label控件
欄 目:C#教程
下一篇:C#判斷單詞個(gè)數(shù)方法總結(jié)
本文標(biāo)題:C#利用GDI+畫圖的基礎(chǔ)實(shí)例教程
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/5221.html
您可能感興趣的文章
- 01-10C#實(shí)現(xiàn)打開畫圖的同時(shí)載入圖片、最大化顯示畫圖窗體的方法
 - 01-10C#利用反射技術(shù)實(shí)現(xiàn)去掉按鈕選中時(shí)的邊框效果
 - 01-10C#圖片處理3種高級應(yīng)用
 - 01-10C#異步下載文件
 - 01-10C# Console利用mspaint打開圖像并保存的方法
 - 01-10C#利用delegate實(shí)現(xiàn)Javascript的each方法
 - 01-10C#利用GDI繪制常見圖形和文字
 - 01-10利用C#實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲
 - 01-10C# 利用ICSharpCode.SharpZipLib實(shí)現(xiàn)在線壓縮和解壓縮
 - 01-10C#利用時(shí)間和隨即字符串創(chuàng)建唯一的訂單編號(hào)
 


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
 - 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
 - 01-10WinForm限制窗體不能移到屏幕外的方法
 - 01-10WinForm繪制圓角的方法
 - 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
 - 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
 - 01-10C#停止線程的方法
 - 01-10C#實(shí)現(xiàn)清空回收站的方法
 - 01-10C#通過重寫Panel改變邊框顏色與寬度的
 - 01-10C#實(shí)現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
 
隨機(jī)閱讀
- 01-10C#中split用法實(shí)例總結(jié)
 - 01-11ajax實(shí)現(xiàn)頁面的局部加載
 - 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 - 04-02jquery與jsp,用jquery
 - 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
 - 01-10delphi制作wav文件的方法
 - 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 


