这篇文章是 GDI+ 总结系列的第二篇,如果对 GDI+ 的基础使用不熟悉的朋友可以先看第一篇文章《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 包含 WidthHeight 属性,读取这两个属性可以获取到文字内容所占的宽高(以像素为单位)。

//
// 摘要:
// 获取或设置此 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();
}
}

最终效果:


系列其他文章:

C# 使用 GDI+ 画图

C# 使用 GDI+ 实现添加中心旋转(任意角度)的文字

C# 使用 GDI+ 给图片添加文字,并使文字自适应矩形区域的更多相关文章

  1. VS2010 MFC 使用GDI+给图片添加汉字

    1.配置GDI+ VS2010自带GDI+,直接使用. (1)首先要添加头文件和库 #pragma comment( lib, "gdiplus.lib" ) #include & ...

  2. ios图片添加文字或者水印

    在项目中,我们会对图片做一些处理,但是我们要记住,一般在客户端做图片处理的数量不宜太多,因为受设备性能的限制,如果批量的处理图片,将会带来交互体验性上的一些问题.首先让我们来看看在图片上添加文字的方法 ...

  3. php 图片添加文字水印 以及 图片合成(微信快码传播)

    1.图片添加文字水印: $bigImgPath = 'backgroud.png'; $img = imagecreatefromstring(file_get_contents($bigImgPat ...

  4. R语言 如何为图片添加文字说明(转载)

    转载:(中文翻译者)[http://blog.csdn.net/chen790646223/article/details/49766659] (原文链接)[http://datascienceplu ...

  5. 利用php给图片添加文字水印--面向对象与面向过程俩种方法的实现

    1: 面向过程的编写方法 //指定图片路径 $src = '001.png'; //获取图片信息 $info = getimagesize($src); //获取图片扩展名 $type = image ...

  6. 一种基于重载的高效c#上图片添加文字图形图片的方法

    在做图片监控显示的时候,需要在图片上添加文字,如果用graphics类绘制图片上的字体,实现图像上添加自定义标记,这种方法经验证是可行的,并且在visual c#2005 编程技巧大全上有提到,但是, ...

  7. Swift - 给图片添加文字水印(图片上写文字,并可设置位置和样式)

    想要给图片添加文字水印或者注释,我们需要实现在UIImage上写字的功能. 1,效果图如下: (在图片左上角和右下角都添加了文字.) 2,为方便使用,我们通过扩展UIImage类来实现添加水印功能 ( ...

  8. C#图片添加文字水印

    /// <summary> /// 给图片添加文字水印 /// </summary> /// <param name="img">图片</ ...

  9. php 图片添加文字,水印

    因为工作需求,用到这个,网上找了很多,也没有找到好的方式,最后找到这种感觉比较简单的方式,记录下来,以备后用.   $im = imagecreatefrompng("img/yyk_bg. ...

随机推荐

  1. ssm实现分页查询

    ssm整合实现分页查询 一.通过limit查询语句实现分页,并展示 1.mapper.xml配置 <select id="selectUsersByPage" paramet ...

  2. 伯克利推出世界最快的KVS数据库Anna:秒杀Redis和Cassandra

    天下武功,唯快不破. 伯克利 RISE 实验室推出了最新的键值存储数据库 Anna,提供了惊人的存取速度.超强的伸缩性和史无前例的一致性保证.Jeff Dean 说,当一个系统增长到十倍规模时,就需要 ...

  3. 分布式协调服务-Zookeeper

    什么是 zookeeper? Zookeeper 是google的chubby一个开源实现,是hadoop的分布式协调服务 它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名 ...

  4. Qt中QComboBox中自定义界面使用stylesheet实现下拉按钮独立效果

    使用QSS自定义控件界面时,QT中控件QCombobox含有两个子控件drop-down和down-arrow.一般而言,当改变QCombox时,很多效果都会出来,但是,针对下拉按钮和下拉图标的自定义 ...

  5. 设计模式——装饰器模式(C++实现)

    #include <iostream> #include <string> using namespace std; class Component { public: ; } ...

  6. USB协议基础知识笔记

    usb协议 功能层: 控制传输.中断传输.块传输(批量传输).同步传输 设备层:管理USB设备.分配地址.读取设备描述符 总线接口层:采用NRZI编码-反向非归零编码(0将前一个电平翻转,1不翻转) ...

  7. struts2和spring mvc的区别

    在项目中使用struts2和spring mvc为了实现后台的业务代码和前台数据之间的传递,现在基本上不会有用struts2的了,几次面试问的最多的关于struts2的问题就是struts2和spri ...

  8. IOS开发之XCode学习014:警告对话框和等待提示器

    此文学习来源为:http://study.163.com/course/introduction/1002858003.htm 此工程文件实现功能:  1.警告对话框和等待提示器的概念 2.警告对话框 ...

  9. curl/libcurl获取打开网页平均网速

    CURL: curl -o /dev/null -s -w %{http_code}:%{http_connect}:%{content_type}:%{time_namelookup}:%{time ...

  10. 前端的UI设计与交互之布局篇

    布局是页面构成的前提,是后续展开交互和视觉设计的基础.设计者在选择布局之前,需要注意以下几点原则:明确用户在此场景中完成的主要任务和需获取的决策信息.明确决策信息和操作的优先级及内容特点,选择合理布局 ...