当前位置:
首页 > Python基础教程 >
-
C#教程之C# 使用 GDI+ 给图片添加文字,并使文字自
需求
需求是要做一个编辑文字的页面。用户在网页端写文字,文字区域是个矩形框,用户可以通过下方的拖动条调节文字大小。
如下图:
提交数据的时候前端传文字区域的左上角和右下角定位给后台。因为前端的字体大小单位与后端没什么关系,所以不能直接传字体大小,也就是后端要根据矩形区域以及文字内容来自己推算用什么样的字体大小合适。
简单说就是知道文字的矩形区域,以及文字内容,要让文字内容根据矩形区域大小调整到适合的字体大小能比较合适地填满这个区域。
分析&思路
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
包含 Width
和 Height
属性,读取这两个属性可以获取到文字内容所占的宽高(以像素为单位)。
//
// 摘要:
// 获取或设置此 System.Drawing.SizeF 结构的水平分量。
//
// 返回结果:
// 此 System.Drawing.SizeF 结构的水平分量,通常以像素为单位进行度量。
public float Width { get; set; }
// 摘要:
// 获取或设置此 System.Drawing.SizeF 结构的垂直分量。
//
// 返回结果:
// 此 System.Drawing.SizeF 结构的垂直分量,通常以像素为单位进行度量。
public float Height { get; set; }
于是我们可以先根据前端传过来的文字左上角与右下角定位,算出文字的矩形区域,然后估计一个字体大小,再用 MeasureString
方法计算出估算的文字所占区域,比较和实际的文字区域大小,大了则缩小字体,小了则增大字体。这样即可大约找出合适的文字大小。
具体实现
- 添加文字方法
/// <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();
}
}
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式