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);
        }