How to draw a line at a precise pixel position

I'm trying to draw a string (single character) in C # to a bitmap at the exact location with:

Bitmap bmp = new Bitmap(64, 64);
Graphics g = Graphics.FromImage(bmp);
g.DrawString("W", font1, new SolidBrush(myColor), new Point(32,32);

      

There is so much white space created around one letter that I cannot guess the "right" position to draw the character to be in the correct position at the end.

By now, I have the exact pixel value for the character (looking at the bits in the separately displayed bitmap). But this information is useless if I cannot draw the character in the exact position (for example, in the center or in the upper right corner or ...).

Are there other methods for drawing text in C # on a bitmap? Or are there any conversion methods to convert the actual pixel position to something that DrawString requires?

+2


source to share


1 answer


No need to look at pixels or start working with your font.

You can use GraphicsPath

instead of DrawString

or TextRenderer

, as it will let you know your mesh border rectangle with GraphicsPath.GetBounds()

.

When you know this, you can calculate how to move the object Graphics

with TranslateTransform

:

enter image description here

private void button1_Click(object sender, EventArgs e)
{
    string text = "Y";                  // whatever
    Bitmap bmp = new Bitmap(64, 64);    // whatever
    bmp.SetResolution(96, 96);          // whatever
    float fontSize = 32f;               // whatever

    using ( Graphics g = Graphics.FromImage(bmp))
    using ( GraphicsPath GP = new GraphicsPath())
    using ( FontFamily fontF = new FontFamily("Arial"))
    {
        testPattern(g, bmp.Size);      // optional

        GP.AddString(text, fontF, 0, fontSize, Point.Empty,
                     StringFormat.GenericTypographic);
        // this is the net bounds without any whitespace:
        Rectangle br = Rectangle.Round(GP.GetBounds());

        g.DrawRectangle(Pens.Red,br); // just for testing

        // now we center:
        g.TranslateTransform( (bmp.Width - br.Width )  / 2 - br.X,
                              (bmp.Height - br.Height )/ 2 - br.Y);
        // and fill
        g.FillPath(Brushes.Black, GP);
        g.ResetTransform();
    }

    // whatever you want to do..
    pictureBox1.Image = bmp;
    bmp.Save("D:\\__test.png", ImageFormat.Png);

}

      



A little test procedure to allow us to see the centering better:

void testPattern(Graphics g, Size sz)
{
    List<Brush> brushes = new List<Brush>() 
    {   Brushes.SlateBlue, Brushes.Yellow, 
        Brushes.DarkGoldenrod, Brushes.Lavender };
    int bw2 = sz.Width / 2;
    int bh2 = sz.Height / 2;
    for (int i = bw2; i > 0; i--)
        g.FillRectangle(brushes[i%4],bw2 - i, bh2 - i, i + i, i + i );

}

      

The method GetBounds

returns a RectangleF

; in my example it is {X=0.09375, Y=6.0625, Width=21, Height=22.90625}

. Note that due to rounding, things can always be off by one.

You may or may not want to change the setting Graphics

to special Smoothingmodes

, etc.

It should also be noted that this will be done automatically, that is, mechanically centered on the border rectangle. This can be very different from "optical or visual centering" , which is rather difficult to code and somewhat personal taste. But typography is as much an art as a profession.

+2


source







All Articles