C#利用GDI+給圖片添加文字(文字自適應(yīng)矩形區(qū)域)
前言
這篇文章是 GDI+ 總結(jié)系列的第二篇,如果對 GDI+ 的基礎(chǔ)使用不熟悉的朋友可以先看第一篇文章《C# 使用 GDI+ 畫圖》。
需求
需求是要做一個編輯文字的頁面。用戶在網(wǎng)頁端寫文字,文字區(qū)域是個矩形框,用戶可以通過下方的拖動條調(diào)節(jié)文字大小。
如下圖:
提交數(shù)據(jù)的時候前端傳文字區(qū)域的左上角和右下角定位給后臺。因?yàn)榍岸说淖煮w大小單位與后端沒什么關(guān)系,所以不能直接傳字體大小,也就是后端要根據(jù)矩形區(qū)域以及文字內(nèi)容來自己推算用什么樣的字體大小合適。
簡單說就是知道文字的矩形區(qū)域,以及文字內(nèi)容,要讓文字內(nèi)容根據(jù)矩形區(qū)域大小調(diào)整到適合的字體大小能比較合適地填滿這個區(qū)域。
分析&思路
Graphics 類有個 MeasureString 方法,可以用來計算以當(dāng)前字體寫出來的文字會占據(jù)多少像素。
如下:
// // 摘要: // 測量用指定的 System.Drawing.Font 繪制的指定字符串。 // // 參數(shù): // text: // 要測量的字符串。 // // font: // System.Drawing.Font,它定義字符串的文本格式。 // // 返回結(jié)果: // 此方法返回 System.Drawing.SizeF 結(jié)構(gòu),該結(jié)構(gòu)表示 text 參數(shù)指定的、使用 font 參數(shù)繪制的字符串的大小,單位由 System.Drawing.Graphics.PageUnit // 屬性指定。 // // 異常: // T:System.ArgumentException: // font 為 null。 public SizeF MeasureString(string text, Font font);
這個方法返回的 SizeF 包含 Width 和 Height 屬性,讀取這兩個屬性可以獲取到文字內(nèi)容所占的寬高(以像素為單位)。
// // 摘要: // 獲取或設(shè)置此 System.Drawing.SizeF 結(jié)構(gòu)的水平分量。 // // 返回結(jié)果: // 此 System.Drawing.SizeF 結(jié)構(gòu)的水平分量,通常以像素為單位進(jìn)行度量。 public float Width { get; set; } // 摘要: // 獲取或設(shè)置此 System.Drawing.SizeF 結(jié)構(gòu)的垂直分量。 // // 返回結(jié)果: // 此 System.Drawing.SizeF 結(jié)構(gòu)的垂直分量,通常以像素為單位進(jìn)行度量。 public float Height { get; set; }
于是我們可以先根據(jù)前端傳過來的文字左上角與右下角定位,算出文字的矩形區(qū)域,然后估計一個字體大小,再用 MeasureString 方法計算出估算的文字所占區(qū)域,比較和實(shí)際的文字區(qū)域大小,大了則縮小字體,小了則增大字體。這樣即可大約找出合適的文字大小。
具體實(shí)現(xiàn)
添加文字方法
/// <summary> /// 圖片添加文字,文字大小自適應(yīng) /// </summary> /// <param name="imgPath">圖片路徑</param> /// <param name="locationLeftTop">左上角定位(x1,y1)</param> /// <param name="locationRightBottom">右下角定位(x2,y2)</param> /// <param name="text">文字內(nèi)容</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); // 計算文字區(qū)域 // 左上角 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]); // 區(qū)域?qū)捀? float fontWidth = x2 - x1; float fontHeight = y2 - y1; float fontSize = fontHeight; // 初次估計先用文字區(qū)域高度作為文字字體大小,后面再做調(diào)整,單位為px Font font = new Font(fontName, fontSize, GraphicsUnit.Pixel); SizeF sf = graph.MeasureString(text, font); int times = 0; // 調(diào)整字體大小以適應(yīng)文字區(qū)域 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},循環(huán)了{(lán)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},循環(huán)了{(lán)1}次", font.ToString(), times); } // 最終的得出的字體所占區(qū)域一般不會剛好等于實(shí)際區(qū)域 // 所以根據(jù)兩個區(qū)域的相差之處再把文字開始位置(左上角定位)稍微調(diào)整一下 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; }
測試調(diào)用
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(); } }
最終效果:
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析
這篇文章主要介紹了C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析,需要的朋友可以參考下2014-07-07C#中ToString數(shù)據(jù)類型格式大全(千分符)
這篇文章主要介紹了C#中ToString數(shù)據(jù)類型格式大全 千分符,需要的朋友可以參考下2017-02-02Unity使用LineRender實(shí)現(xiàn)繪畫功能
這篇文章主要為大家詳細(xì)介紹了Unity使用LineRender實(shí)現(xiàn)繪畫功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-07-07C#使用BitConverter與BitArray類進(jìn)行預(yù)定義基礎(chǔ)類型轉(zhuǎn)換
這篇文章介紹了C#使用BitConverter與BitArray類進(jìn)行預(yù)定義基礎(chǔ)類型轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05