C# 使用 GDI+ 实现添加中心旋转(任意角度)的文字
这篇文章是 GDI+
总结系列的第三篇,如果对 GDI+
的基础使用不熟悉的朋友可以先看第一篇文章《C# 使用 GDI+ 画图》。
需求
需求是要实现给图片添加任意角度旋转的文字,文字的旋转中心要是在文字区域中央,就像 CSS
的 rotate
函数一样的效果。如下:
分析&思路
Graphics
类有个 RotateTransform
方法,可以传入任意角度的值来旋转画板。但是这个方法的旋转中心是画板的左上角,所以直接单单用这个方法不能满足我们的需求。此外,Graphics
类还有个 TranslateTransform
方法可以改变坐标的原点,而且这个方法是沿着矩形的x,y轴平移的,即就算图片旋转了一定的角度后,再调用 TranslateTransform
方法,它还是沿着x,y轴平移。于是通过以下三个步骤即可实现图片中心旋转。
- 把画板(Graphics对象)原点平移到矩形中心位置(x, y)
- 在(x, y)位置绕原点旋转画板N度
- 画板退回(-x, -y)的距离
还是看不懂的同学看下面的图应该就明白了
明白了原理,那不容易推断出,如果要旋转的中心不是图片中心而是文字中心,那步骤还是一样的,只是把(x, y)改为文字中心的坐标就好了。
除了上面说的方法,其实还有一个方法可以实现中心旋转,那就是使用 Matrix
类。Matrix
类的 RotateAt
方法可以指定矩阵旋转的中心位置。
//
// 摘要:
// 沿 point 参数中指定的点并通过预先计算该旋转,来顺时针旋转此 System.Drawing.Drawing2D.Matrix。
//
// 参数:
// angle:
// 旋转角度(范围)(单位:度)。
//
// point:
// 一个 System.Drawing.PointF,表示旋转中心。
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public void RotateAt(float angle, PointF point);
Graphics
类的 Transform
属性返回的就是 Matrix
对象,该属性可以 get
、set
。因此我们先获取原来的画板的矩阵,然后使用 RotateAt
方法旋转该矩阵,再把旋转后的矩阵赋值给画板就好了。
具体实现
- 添加任意角度文字方法
/// <summary>
/// 图片添加任意角度文字(文字旋转是中心旋转,角度顺时针为正)
/// </summary>
/// <param name="imgPath">图片路径</param>
/// <param name="locationLeftTop">文字左上角定位(x1,y1)</param>
/// <param name="fontSize">字体大小,单位为像素</param>
/// <param name="text">文字内容</param>
/// <param name="angle">文字旋转角度</param>
/// <param name="fontName">字体名称</param>
/// <returns>添加文字后的Bitmap对象</returns>
public Bitmap AddText(string imgPath, string locationLeftTop, int fontSize, string text, int angle = 0, string fontName = "华文行楷")
{
Image img = Image.FromFile(imgPath);
int width = img.Width;
int height = img.Height;
Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);
// 画底图
graphics.DrawImage(img, 0, 0, width, height);
Font font = new Font(fontName, fontSize, GraphicsUnit.Pixel);
SizeF sf = graphics.MeasureString(text, font); // 计算出来文字所占矩形区域
// 左上角定位
string[] location = locationLeftTop.Split(',');
float x1 = float.Parse(location[0]);
float y1 = float.Parse(location[1]);
// 进行文字旋转的角度定位
if (angle != 0)
{
#region 法一:TranslateTransform平移 + RotateTransform旋转
/*
* 注意:
* Graphics.RotateTransform的旋转是以Graphics对象的左上角为原点,旋转整个画板的。
* 同时x,y坐标轴也会跟着旋转。即旋转后的x,y轴依然与矩形的边平行
* 而Graphics.TranslateTransform方法,是沿着x,y轴平移的
* 因此分三步可以实现中心旋转
* 1.把画板(Graphics对象)平移到旋转中心
* 2.旋转画板
* 3.把画板平移退回相同的距离(此时的x,y轴仍然是与旋转后的矩形平行的)
*/
//// 把画板的原点(默认是左上角)定位移到文字中心
//graphics.TranslateTransform(x1 + sf.Width / 2, y1 + sf.Height / 2);
//// 旋转画板
//graphics.RotateTransform(angle);
//// 回退画板x,y轴移动过的距离
//graphics.TranslateTransform(-(x1 + sf.Width / 2), -(y1 + sf.Height / 2));
#endregion
#region 法二:矩阵旋转
Matrix matrix = graphics.Transform;
matrix.RotateAt(angle, new PointF(x1 + sf.Width / 2, y1 + sf.Height / 2));
graphics.Transform = matrix;
#endregion
}
// 写上自定义角度的文字
graphics.DrawString(text, font, new SolidBrush(Color.Black), x1, y1);
graphics.Dispose();
img.Dispose();
return bmp;
}
PS:这里简单解释一下为什么文字中心是 (x1 + sf.Width / 2, y1 + sf.Height / 2)
,因为 (x, y)
是左上角,而 sf.Width
、sf.Height
是文字矩形区域宽、高。如图:
- 测试调用
private static void Main(string[] args)
{
try
{
Console.WriteLine("Start drawing ...");
DrawingEntity drawing = new DrawingEntity();
System.Drawing.Bitmap bmp = drawing.AddText(@"D:\test\1.png", "176.94,150.48", 66, "写点啥好呢", 30);
bmp.Save(@"D:\test\output.png");
bmp.Dispose();
Console.WriteLine("Done!");
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
System.Console.WriteLine("\nPress any key to continue ...");
System.Console.ReadKey();
}
}
最终效果
没有旋转时
中心旋转30度
一个思考
讲完了大家来思考一个问题,如果我想做图片绕任意位置为中心进行旋转应该怎么做呢?相信看完了上面的代码大家应该都会了吧。
参考文章:
C#中基于GDI+(Graphics)图像处理系列之任意角度旋转图像
C#利用GDI+绘制旋转文字,矩形内可以根据布局方式排列文本
系列其他文章:
C# 使用 GDI+ 给图片添加文字,并使文字自适应矩形区域
C# 使用 GDI+ 实现添加中心旋转(任意角度)的文字的更多相关文章
- 在图片不被裁剪时opencv绕图片中任意点旋转任意角度
opencv绕图片中任意角度旋转任意角度 最近在做项目需要把把图片绕图片中任意点旋转任意角度,考虑到自己旋转需要编写插值算法,所以想到了用opencv,但是网上都是围绕图片中点旋转任意角度的,都是 ...
- JQuery插件让图片旋转任意角度且代码极其简单
引入下方的jquery.rotate.js文件,然后通过$("选择器").rotate(角度);可以旋转任意角度, 例如$("#rotate-image").r ...
- JQuery插件让图片旋转任意角度且代码极其简单 - 摘自网友
JQuery插件让图片旋转任意角度且代码极其简单 2012-04-01 09:57:03 我来说两句 收藏 我要投稿 引入下方的jquery.rotate.js文件,然后通过$ ...
- UIImageView旋转任意角度
-(UIImageView *) makeRotation:(UIImageView *)image speedX:(float)X speedY:(float)Y { // 头文件中需要定义 ...
- PS 旋转任意角度的照片
1.选择标尺工具 2.在图片上画一个线,然后工具栏--图像--图像旋转
- UIImageView旋转任意角度---实现方法
转自:http://blog.csdn.net/trandy/article/details/6626281 -(UIImageView *) makeRotation:(UIImageView *) ...
- windows api(GDI)实现图片旋转
GDI实现图片旋转,博主在网上找了好多资料,都不太如意. 并且在尝试中发现,如果先用SetViewportOrgEx将HDC上的坐标原点移动到图片中心:再在HDC上的获取每个点,用三角函数进行变换,算 ...
- 在word中输入任意角度旋转图片
Sub 图片旋转任意角度() Dim sha As Shape, isa As InlineShape Static s As Integer Application.ScreenUpdating = ...
- JAVA对图片的任意角度旋转,以及镜像操作
package relevantTest;/* * 该代码实现了对图像的水平镜像变换,垂直镜像变换,任意角度旋转,jtf的实时监控,以及对图像的缩放变换,以及按钮的若隐若现效果. * 在对图像进行任意 ...
随机推荐
- NancyFX 第八章 内容协商
在Web框架的范畴内,一切都是基于REST的-- 从返回包含CSS.JavaScript的网页的路由路径,到那些返回JSON数据的URL. 无论你怎么看它,两者都是必须的.我们使用一组URL来呈现UR ...
- Django---第三方
第三方: 3.富文本编辑器:此处以tinymce为例 使用编辑器的显示效果为: 1.下载安装 在网站pypi网站搜索并下载"django-tinymce-2.4.0" 解压 tar ...
- 记一次线上Curator使用过程JVM栈溢出解决
为了同学们看起来一目了,特按如下思路进行讲解. 1.出现的场景 2.分析及解决的过程 3.总结 最近公司要使用zookeeper做配置管理(后面简称ZK),然后自己就提前用虚拟机进行 ...
- MarkDown 的使用学习
以下都是MarkDown常用的语法以及效果图: ### 生成目录 [TOC] ### 标题 标题的标签采用#加文本的形式,几个星就代表几级标题 在#后加空格 # 一级标题 ## 二级标题 ... # ...
- 面向对象设计模式_命令模式(Command)解读
在.Net框架中很多对象的方法中都会有Invoke方法,这种方法的设计实际是用了设计模式的命令模式, 模式图如下 其核心思路是将Client 向Receiver发送的命令行为进行抽象(ICommand ...
- 使用shutdown命令实现局域网内远程关机、重启整蛊他人
用法: shutdown [/i | /l | /s | /r | /g | /a | /p | /h | /e | /o] [/hybrid] [/soft] [/f] [/m \\compu ...
- 设计模式——原型模式(C++实现)
#include <iostream> #include <string> using namespace std; class CPrototype { public: CP ...
- puppet客户端拉取服务端的资源时报错
2017-11-01 16:21:47 客户端再拉取服务端的配置的资源时,出现一下报错: 造成原因:服务配置的资源不可用: 解决办法:将服务端不正确的资源配置删除: master: cd ...
- 写了个批量查询qs的软件
因为需要,自己写了个批量查询qs的小软件.从网站中抓出需要的数据,格式化显示: 对字符串进行检测处理,先用Replace函数去掉字符串的空格,再用正则表达式匹配,返回匹配的字符串,如果没有匹配,则返回 ...
- SpringtMVC中配置 <mvc:annotation-driven/> 与 <mvc:default-servlet-handler/> 的作用与源码解析
基于 Spring4.X 来学习 SpringtMVC, 在学习过程中,被"告知"在 XML 配置文件中建议设置如下两项: 一直不明白为什么,但又甘心.于是,花了一点时间来调试源码 ...