C# 从右角开始旋转 DrawString
C# Rotated DrawString from Right Corner
我正在尝试在图像上从右上角向左下角绘制文本。我的代码弄乱了拉绳的定位。到目前为止,这段代码是这样绘制的,但我需要帮助在这些红线之间绘制文本。
string img_src = "F:\blank_imge.jpg";
System.Drawing.Image selected_img = System.Drawing.Image.FromFile(img_src);
using(Graphics gr = Graphics.FromImage(selected_img))
{
Font font = new Font("Arial", 2.0f);
int x = selected_img.Width;
int y = 0;
for (int b = 1; b <= 5; b++)
{
GraphicsState state = gr.Save();
gr.ResetTransform();
int opacity = 35;
string txt = "watermark";
using (Brush brush = new SolidBrush(Color.FromArgb(opacity, 255, 255, 255)))
{
SizeF textSize = gr.MeasureString("watermark", font);
gr.RotateTransform(45);
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
gr.DrawString(txt, font, brush, new PointF(x - textSize.Width, y));
}
y = y + 25;
gr.Restore(state);
}
selected_img.Save("F:\watermarked.jpg");
}
您需要先翻译它才能移动原点:
类似于:
gr.TranslateTransform(x, y);
gr.RotateTransform(45);
gr.TranslateTransform(-x, -y);
您可以先测量字符串的长度以确定文本的中心。
伪..
var size = gr.MeasureString(txt, font);
var halfWidth = size.X / 2;
var halfHeight = size.X / 2;
gr.TranslateTransform(halfWidth , halfHeight);
gr.RotateTransform(45);
gr.TranslateTransform(-halfWidth , -halfHeight);
未测试...
您的问题似乎至少有两个子问题:
- 沿对角线绘制:您的示例似乎表明您希望将每行文本垂直于次对角线书写,所以我会这样做。
- 我假设我们在谈论矩形,所以 45 度部分只是愚蠢的,添加了计算真实角度的代码
- 在带内绘制我不知道你的问题是定位还是保持字符串宽度在范围内。
下面的代码解决了 沿对角线绘制 部分,以获得正确的定位部分。在我看来,将内容放入 "band" 更容易解决(您必须使用 g.MeasureString 循环直到内容适合或换行,我不知道确切的要求)。如果您需要更多说明,请告诉我。
我已尝试在代码中加入注释,但如果有任何需要清理的地方请告诉我。
我希望在 SO 上格式化代码会更容易...
public class DiagonalLines
{
private readonly Font font;
private readonly Brush brush = new SolidBrush(Color.Black);
private readonly Image image;
private readonly float width;
private readonly float height;
private readonly float diagonalAngle;
private readonly string savePath;
public DiagonalLines(string path, string savePath)
{
this.image = Image.FromFile(path);
width = image.Width;
height = image.Height;
//this could be optimized
//you want to write perpendicular to the secondary diagonal, if I understood correctly
//Math.Atan(height / width) => angle, in radians of the first diagonal
//after applying "-" we obtain the angle, in radians, of the secondary diagonal
//the rest of the first term is converting radians to degrees
diagonalAngle = -(float)(Math.Atan(height / width) * 180 / Math.PI) + /* perpendicular*/ 90;
this.font = new Font("Arial", (float)image.Width / 80); //write about 80 characters for a full horizontal text line
this.savePath = savePath;
}
public void DrawLines(params string[] lines)
{
using (Graphics g = Graphics.FromImage(image))
{
//M should be the largest character in most "western" fonts
var lineHeight = g.MeasureString("M", font).Height;
var halfTheLines = (float)lines.Length / 2; //about half the lines should be "above" the midpoint of the secondary diagonal
var offsetY = -(halfTheLines * lineHeight); //we scale the position against the line height
//same effect could probably be achieved with ScaleTransform
g.DrawLine(Pens.Red, 0, height, width, 0); //draw the secondary diagonal
foreach (var val in lines)
{
var size = g.MeasureString(val, font);
g.ResetTransform();
g.TranslateTransform(width / 2, height / 2); //go to center of image
g.RotateTransform(diagonalAngle);
//translate, to center the text and apply our offset
g.TranslateTransform(-size.Width / 2, -size.Height / 2 + offsetY);
g.DrawString(val, font, brush, 0, 0);
offsetY += lineHeight;
}
}
image.Save(savePath);
}
}
static void Main(string[] args)
{
var lines = new DiagonalLines("c:\temp\img\poza.png", "c:\temp\img\watermarked.jpg");
lines.DrawLines("this", "that", "the other", "and another");
Process.Start("c:\temp\img\watermarked.jpg");
}
我更愿意这样写。里面有很多小变化...仔细看!
using (Graphics gr = Graphics.FromImage(selected_img))
{
int y = -50;
int opacity = 127; // 0 to 255
string txt = "watermark";
int x = selected_img.Width;
GraphicsState state = gr.Save();
gr.ResetTransform();
gr.TranslateTransform(selected_img.Width / 2, selected_img.Height / 2);
gr.RotateTransform(45);
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
using (Font font = new Font("Arial", 14.0f))
{
SizeF textSize = gr.MeasureString(txt, font);
using (Brush brush = new SolidBrush(Color.FromArgb(opacity, Color.DarkGray)))
{
for (int b = 1; b <= 5; b++, y += 25)
{
gr.DrawString(txt, font, brush, new PointF(-(textSize.Width / 2), y));
}
}
}
gr.Restore(state);
}
我正在尝试在图像上从右上角向左下角绘制文本。我的代码弄乱了拉绳的定位。到目前为止,这段代码是这样绘制的,但我需要帮助在这些红线之间绘制文本。
string img_src = "F:\blank_imge.jpg";
System.Drawing.Image selected_img = System.Drawing.Image.FromFile(img_src);
using(Graphics gr = Graphics.FromImage(selected_img))
{
Font font = new Font("Arial", 2.0f);
int x = selected_img.Width;
int y = 0;
for (int b = 1; b <= 5; b++)
{
GraphicsState state = gr.Save();
gr.ResetTransform();
int opacity = 35;
string txt = "watermark";
using (Brush brush = new SolidBrush(Color.FromArgb(opacity, 255, 255, 255)))
{
SizeF textSize = gr.MeasureString("watermark", font);
gr.RotateTransform(45);
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
gr.DrawString(txt, font, brush, new PointF(x - textSize.Width, y));
}
y = y + 25;
gr.Restore(state);
}
selected_img.Save("F:\watermarked.jpg");
}
您需要先翻译它才能移动原点:
类似于:
gr.TranslateTransform(x, y);
gr.RotateTransform(45);
gr.TranslateTransform(-x, -y);
您可以先测量字符串的长度以确定文本的中心。
伪..
var size = gr.MeasureString(txt, font);
var halfWidth = size.X / 2;
var halfHeight = size.X / 2;
gr.TranslateTransform(halfWidth , halfHeight);
gr.RotateTransform(45);
gr.TranslateTransform(-halfWidth , -halfHeight);
未测试...
您的问题似乎至少有两个子问题:
- 沿对角线绘制:您的示例似乎表明您希望将每行文本垂直于次对角线书写,所以我会这样做。
- 我假设我们在谈论矩形,所以 45 度部分只是愚蠢的,添加了计算真实角度的代码
- 在带内绘制我不知道你的问题是定位还是保持字符串宽度在范围内。
下面的代码解决了 沿对角线绘制 部分,以获得正确的定位部分。在我看来,将内容放入 "band" 更容易解决(您必须使用 g.MeasureString 循环直到内容适合或换行,我不知道确切的要求)。如果您需要更多说明,请告诉我。
我已尝试在代码中加入注释,但如果有任何需要清理的地方请告诉我。 我希望在 SO 上格式化代码会更容易...
public class DiagonalLines
{
private readonly Font font;
private readonly Brush brush = new SolidBrush(Color.Black);
private readonly Image image;
private readonly float width;
private readonly float height;
private readonly float diagonalAngle;
private readonly string savePath;
public DiagonalLines(string path, string savePath)
{
this.image = Image.FromFile(path);
width = image.Width;
height = image.Height;
//this could be optimized
//you want to write perpendicular to the secondary diagonal, if I understood correctly
//Math.Atan(height / width) => angle, in radians of the first diagonal
//after applying "-" we obtain the angle, in radians, of the secondary diagonal
//the rest of the first term is converting radians to degrees
diagonalAngle = -(float)(Math.Atan(height / width) * 180 / Math.PI) + /* perpendicular*/ 90;
this.font = new Font("Arial", (float)image.Width / 80); //write about 80 characters for a full horizontal text line
this.savePath = savePath;
}
public void DrawLines(params string[] lines)
{
using (Graphics g = Graphics.FromImage(image))
{
//M should be the largest character in most "western" fonts
var lineHeight = g.MeasureString("M", font).Height;
var halfTheLines = (float)lines.Length / 2; //about half the lines should be "above" the midpoint of the secondary diagonal
var offsetY = -(halfTheLines * lineHeight); //we scale the position against the line height
//same effect could probably be achieved with ScaleTransform
g.DrawLine(Pens.Red, 0, height, width, 0); //draw the secondary diagonal
foreach (var val in lines)
{
var size = g.MeasureString(val, font);
g.ResetTransform();
g.TranslateTransform(width / 2, height / 2); //go to center of image
g.RotateTransform(diagonalAngle);
//translate, to center the text and apply our offset
g.TranslateTransform(-size.Width / 2, -size.Height / 2 + offsetY);
g.DrawString(val, font, brush, 0, 0);
offsetY += lineHeight;
}
}
image.Save(savePath);
}
}
static void Main(string[] args)
{
var lines = new DiagonalLines("c:\temp\img\poza.png", "c:\temp\img\watermarked.jpg");
lines.DrawLines("this", "that", "the other", "and another");
Process.Start("c:\temp\img\watermarked.jpg");
}
我更愿意这样写。里面有很多小变化...仔细看!
using (Graphics gr = Graphics.FromImage(selected_img))
{
int y = -50;
int opacity = 127; // 0 to 255
string txt = "watermark";
int x = selected_img.Width;
GraphicsState state = gr.Save();
gr.ResetTransform();
gr.TranslateTransform(selected_img.Width / 2, selected_img.Height / 2);
gr.RotateTransform(45);
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
using (Font font = new Font("Arial", 14.0f))
{
SizeF textSize = gr.MeasureString(txt, font);
using (Brush brush = new SolidBrush(Color.FromArgb(opacity, Color.DarkGray)))
{
for (int b = 1; b <= 5; b++, y += 25)
{
gr.DrawString(txt, font, brush, new PointF(-(textSize.Width / 2), y));
}
}
}
gr.Restore(state);
}