C# 使用 GDI+ 畫圖

最近作一個微信公衆號服務,有一些簡單的圖片處理功能。主要就是用戶在頁面操做,前端作一些馬上顯示的效果,而後提交保存時後端真正修改原圖。
咱們的後端是 ASP.NET,也就是 C# 語言了,C# 自己處理圖片仍是比較方便的,使用 GDI+ 就好,只須要添加 System.Drawing 引用,不須要任何第三方庫。因而最近也用到一些比較經常使用的 GDI+ 圖片處理方法,就整理一下作個記錄了。html

這個題目大概會寫幾篇文章,第一篇先簡單介紹一下 GDI+ 的經常使用對象,以及一些使用時候的注意事項,後面會挑一些項目中作過的比較有用的處理過程來介紹一下。前端

廢話很少說,開始進入正題。後端


須要用到的類

使用 GDI+ 畫圖會用到的幾個經常使用的類有:GraphicsBitmapImage
其中 Graphics 是畫板。這個類包含了許多畫圖的方法,包括畫圖片(DrawImage),畫線(DrawLine),畫圓(DrawEllipse、FillEllipse),寫字(DrawString)等等。簡單說使用這個類能夠完成咱們須要的大部分工做。微信

生成一個 Graphics 對象須要用到 Image 或者 Bitmap
PS: Winform 下能夠直接從窗體或控件的事件中引用 Graphics 對象。 好比:函數

private void Form1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics; // 建立畫板,這裏的畫板是由Form提供的.
    }

不過本文討論的是其餘場景,好比 ASP.NET MVC,或單純的控制檯程序。這些時候是沒有控件的,因此要用其餘方法。spa

我通常用如下方法:code

//
// 摘要:
//     從指定的 System.Drawing.Image 建立新的 System.Drawing.Graphics。
//
// 參數:
//   image:
//     從中建立新 System.Drawing.Graphics 的 System.Drawing.Image。
//
// 返回結果:
//     此方法爲指定的 System.Drawing.Image 返回一個新的 System.Drawing.Graphics。
//
// 異常:
//   T:System.ArgumentNullException:
//     image 爲 null。
//
//   T:System.Exception:
//     image 具備索引像素格式,或者格式未定義。
public static Graphics FromImage(Image image);

其中的參數能夠傳入 ImageBitmap,由於 Bitmap 是繼承自 Image 的。orm


如何建立畫板

  • 若是是要對原圖進行處理,好比旋轉圖片,添加文字等,能夠直接經過原圖片得到畫板對象。
Image img = Image.FromFile(imgPath);
Graphics graphics = Graphics.FromImage(img);
  • 若是是要畫一個新的圖,能夠經過要保存的圖片寬、高生成畫板。
Bitmap bmp = new Bitmap(width, height);
Graphics graph = Graphics.FromImage(bmp);

PS: Graphics 自己是沒有提供構造函數來直接生成的。因此咱們能夠先建立一個須要保存圖片大小的 Bitmap 位圖對象,而後再得到畫板對象。htm


如何保存畫好的圖片

經過調用 img.Save(savePath) 或者 bmp.Save(savePath) 便可保存對象。
PS: BitmapSave 方法是直接繼承自 Image 的。對象


GDI+ 的座標系

GDI+ 的座標系是個二維座標系,不過又有點不同,它的原點是在左上角的。以下圖:


使用 GDI+ 的一些注意事項

這裏我忍不住要先吐槽一下,GDI+ 的報錯信息不太友好啊。常常只是返回一個「GDI+ 中發生通常性錯誤。」,不能快速地根據這個錯誤提示定位問題。好比說沒有釋放圖片資源時想再次訪問資源會報這個錯誤,想要保存圖片的文件夾不存在時也是提示這個錯誤。看不出來區別……

1. 保存到相同路徑的文件時要先釋放圖片資源,不然會報錯(GDI+中發生通常性錯誤)

Image img = Image.FromFile(imgPath);
Bitmap bmp = new Bitmap(img);
Graphics graphics = Graphics.FromImage(bmp);
... // 對圖片進行一些處理
img.Dispose(); // 釋放原圖資源
bmp.Save(imgPath); // 保存到原圖
graphics.Dispose(); // 圖片處理過程完成,剩餘資源所有釋放
bmp.Dispose();

2. 使用完的資源記得要釋放。能夠用 try..catch..finally 或者 using 的方式,這樣即便遇到代碼運行報錯也能及時釋放資源,更加保險。

  • 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 語句建立的資源會在離開 using 代碼段時自動釋放該資源。
/// <summary>
    /// 縮放圖像
    /// </summary>
    /// <param name="originalImagePath">原圖路徑</param>
    /// <param name="destWidth">目標圖寬度</param>
    /// <param name="destHeight">目標圖高度</param>
    /// <returns></returns>
    public Bitmap GetThumbnail(string originalImagePath, int destWidth, int destHeight)
    {
        using (Image imgSource = Image.FromFile(originalImagePath))
        {
            return GetThumbnail(imgSource, destWidth, destHeight);
        }
    }

3. 要保存圖片的文件夾必定要是已經存在的,不然會報錯(GDI+中發生通常性錯誤)

eg:假設圖片要保存到 D:\test\output.png

string directory = @"D:\test\";
    string fileName = "output.png";

    // 檢查文件夾是否存在,不存在則先建立
    if (!Directory.Exists(directory))
    {
        Directory.CreateDirectory(directory);
    }

    bmp.Save(directory + fileName);

系列其餘文章: C# 使用 GDI+ 給圖片添加文字,並使文字自適應矩形區域 C# 使用 GDI+ 實現添加中心旋轉(任意角度)的文字

相關文章
相關標籤/搜索