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?
source to share
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
:
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.
source to share