2

I am trying to draw text on an image from top right corner towards the bottom left corner. My code mess up the positioning of drawstring. so far this code drawing like this but I need help to draw text between these red lines.

enter image description here

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");
    }
aadi1295
  • 982
  • 3
  • 19
  • 47
  • 1
    RotateTransform almost always needs to be surrounded by suitable TranslateTransforms – TaW Feb 08 '19 at 15:06

3 Answers3

3

You need to translate it first to move the origin:

Something like:

 gr.TranslateTransform(x, y);
 gr.RotateTransform(45);
 gr.TranslateTransform(-x, -y);

You can measure the length of the string first to determine the center of the text.

PSEUDO..

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

Not tested...

Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
2

I'd write it more like this. There are lots of little changes in there...look closely!

        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);
        }
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
1

Your question seems to have at least two sub-questions:

  • Draw along a diagonal: your sample seems to indicate that you want to write each line of text perpendicularly to the secondary diagonal, so I will go with that.
  • I assumed we are talking Rectangles, so the 45 degree part is just silly, added code to calculate the real angle
  • Draw within a band I do not know if your problem is positioning or keeping a string width within the bounds.

The code below addresses the Draw along a diagonal part, to get the positioning part right. Fitting things in a "band" in my opinion is easier to address (you have to loop through with a g.MeasureString until things fit or wrap text, I do not know the exact requirements). Let me know if you need more clarification.

enter image description here

I've tried to include comments in the code, but let me know if anything needs clearing up. I wish formatting code would be easier on 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");
}
Alexandru Clonțea
  • 1,746
  • 13
  • 23