C# 使用 GDI+ 給圖片添加文字,並使文字自適應矩形區域

這篇文章是 GDI+ 總結系列的第二篇,若是對 GDI+ 的基礎使用不熟悉的朋友能夠先看第一篇文章《C# 使用 GDI+ 畫圖》html


需求

需求是要作一個編輯文字的頁面。用戶在網頁端寫文字,文字區域是個矩形框,用戶能夠經過下方的拖動條調節文字大小。
以下圖:
前端

提交數據的時候前端傳文字區域的左上角和右下角定位給後臺。由於前端的字體大小單位與後端沒什麼關係,因此不能直接傳字體大小,也就是後端要根據矩形區域以及文字內容來本身推算用什麼樣的字體大小合適。後端

簡單說就是知道文字的矩形區域,以及文字內容,要讓文字內容根據矩形區域大小調整到適合的字體大小能比較合適地填滿這個區域。測試


分析&思路

Graphics 類有個 MeasureString 方法,能夠用來計算以當前字體寫出來的文字會佔據多少像素。
以下:字體

//
// 摘要:
//     測量用指定的 System.Drawing.Font 繪製的指定字符串。
//
// 參數:
//   text:
//     要測量的字符串。
//
//   font:
//     System.Drawing.Font,它定義字符串的文本格式。
//
// 返回結果:
//     此方法返回 System.Drawing.SizeF 結構,該結構表示 text 參數指定的、使用 font 參數繪製的字符串的大小,單位由 System.Drawing.Graphics.PageUnit
//     屬性指定。
//
// 異常:
//   T:System.ArgumentException:
//     font 爲 null。
public SizeF MeasureString(string text, Font font);

這個方法返回的 SizeF 包含 WidthHeight 屬性,讀取這兩個屬性能夠獲取到文字內容所佔的寬高(以像素爲單位)。spa

//
// 摘要:
//     獲取或設置此 System.Drawing.SizeF 結構的水平份量。
//
// 返回結果:
//     此 System.Drawing.SizeF 結構的水平份量,一般以像素爲單位進行度量。
public float Width { get; set; }

// 摘要:
//     獲取或設置此 System.Drawing.SizeF 結構的垂直份量。
//
// 返回結果:
//     此 System.Drawing.SizeF 結構的垂直份量,一般以像素爲單位進行度量。
public float Height { get; set; }

因而咱們能夠先根據前端傳過來的文字左上角與右下角定位,算出文字的矩形區域,而後估計一個字體大小,再用 MeasureString 方法計算出估算的文字所佔區域,比較和實際的文字區域大小,大了則縮小字體,小了則增大字體。這樣便可大約找出合適的文字大小。code


具體實現

  • 添加文字方法
/// <summary>
    /// 圖片添加文字,文字大小自適應
    /// </summary>
    /// <param name="imgPath">圖片路徑</param>
    /// <param name="locationLeftTop">左上角定位(x1,y1)</param>
    /// <param name="locationRightBottom">右下角定位(x2,y2)</param>
    /// <param name="text">文字內容</param>
    /// <param name="fontName">字體名稱</param>
    /// <returns>添加文字後的Bitmap對象</returns>
    public static Bitmap AddText(string imgPath, string locationLeftTop, string locationRightBottom, string text, string fontName = "華文行楷")
    {
        Image img = Image.FromFile(imgPath);

        int width = img.Width;
        int height = img.Height;
        Bitmap bmp = new Bitmap(width, height);
        Graphics graph = Graphics.FromImage(bmp);

        // 計算文字區域
        // 左上角
        string[] location = locationLeftTop.Split(',');
        float x1 = float.Parse(location[0]);
        float y1 = float.Parse(location[1]);
        // 右下角
        location = locationRightBottom.Split(',');
        float x2 = float.Parse(location[0]);
        float y2 = float.Parse(location[1]);
        // 區域寬高
        float fontWidth = x2 - x1;
        float fontHeight = y2 - y1;

        float fontSize = fontHeight;  // 初次估計先用文字區域高度做爲文字字體大小,後面再作調整,單位爲px

        Font font = new Font(fontName, fontSize, GraphicsUnit.Pixel);
        SizeF sf = graph.MeasureString(text, font);

        int times = 0;

        // 調整字體大小以適應文字區域
        if (sf.Width > fontWidth)
        {
            while (sf.Width > fontWidth)
            {
                fontSize -= 0.1f;
                font = new Font(fontName, fontSize, GraphicsUnit.Pixel);
                sf = graph.MeasureString(text, font);

                times++;
            }

            Console.WriteLine("一開始估計大了,最終字體大小爲{0},循環了{1}次", font.ToString(), times);
        }
        else if (sf.Width < fontWidth)
        {
            while (sf.Width < fontWidth)
            {
                fontSize += 0.1f;
                font = new Font(fontName, fontSize, GraphicsUnit.Pixel);
                sf = graph.MeasureString(text, font);

                times++;
            }

            Console.WriteLine("一開始估計小了,最終字體大小爲{0},循環了{1}次", font.ToString(), times);
        }

        // 最終的得出的字體所佔區域通常不會恰好等於實際區域
        // 因此根據兩個區域的相差之處再把文字開始位置(左上角定位)稍微調整一下
        x1 += (fontWidth - sf.Width) / 2;
        y1 += (fontHeight - sf.Height) / 2;

        graph.DrawImage(img, 0, 0, width, height);
        graph.DrawString(text, font, new SolidBrush(Color.Black), x1, y1);

        graph.Dispose();
        img.Dispose();

        return bmp;
    }
  • 測試調用
private static void Main(string[] args)
    {
        try
        {
            DrawingEntity drawing = new DrawingEntity();

            Console.WriteLine("Start drawing ...");
            System.Drawing.Bitmap bmp = drawing.AddText(@"D:\test\39585148.png", "177.75,63.84", "674.73, 141.6", "大海啊,全是浪");
            bmp.Save(@"D:\test\output.png");
            bmp.Dispose();
            Console.WriteLine("Done!");
        }
        catch (System.Exception ex)
        {
            Console.WriteLine("出錯了!!\n" + ex.ToString());
        }
        finally
        {
            System.Console.WriteLine("\nPress any key to continue ...");
            System.Console.ReadKey();
        }
    }

最終效果: htm


系列其餘文章: C# 使用 GDI+ 畫圖 C# 使用 GDI+ 實現添加中心旋轉(任意角度)的文字對象

相關文章
相關標籤/搜索