如何在精确的像素位置绘制字符串

时间:2015-10-15 12:25:32

标签: c# .net graphics bitmap drawstring

我尝试将C#中的字符串(单个字符)绘制到位图的精确位置:

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

在一个字母周围有很多空白空间,我无法猜到“需要”的位置来绘制角色,使其在最后的正确位置。

到目前为止,我有像素的精确尺寸(查看单独渲染的位图中的位)。但是如果我不能在准确位置(例如中心或右上角或......)绘制角色,这些信息就没用了。

是否还有其他方法可以在位图上用C#绘制文本?或者是否有任何转换方法来转换DrawString需要的实际像素位置?

1 个答案:

答案 0 :(得分:3)

无需查看像素或开始使用自己的字体..

您可以使用GraphicsPath代替DrawStringTextRenderer,因为它会通过GraphicsPath.GetBounds()通知您净边界矩形

如果您知道,可以使用Graphics计算如何移动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);

}

让我们更好地看到中心的小型测试程序:

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

}

GetBounds方法返回RectangleF;在我的例子中,它是{X=0.09375, Y=6.0625, Width=21, Height=22.90625}。请注意,由于四舍五入的事情总是一个接一个..

您可能希望也可能不希望将Graphics设置更改为特殊Smoothingmodes等。

另外应该注意的是,这将通过边界矩形进行自动即机械定心。这可能与'optical or visual centering'完全不同,后者很难编码,在某种程度上也是个人品味的问题。但排版既是一种艺术也是一种职业。