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

How to draw a string at an exact pixel position(如何在精确的像素位置绘制字符串)
本文介绍了如何在精确的像素位置绘制字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I try to draw a string (single character) in C# into a Bitmap at an exact position 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 empty space rendered around a single letter, that I can not guess the "needed" position to draw the character to have it at the correct position at the end.

现在我有了字符的像素精确尺寸(查看单独呈现的位图中的位).但是如果我不能在一个确切的位置(例如中心或右上角或....)绘制字符,这些信息是无用的.

By now I have the pixel exact dimension of the character (looking at bits in a separately rendered bitmap). But this information is useless, if I cannot draw the character at an exact position (e.g. center or top right corner or ....).

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

Are there other methods to draw text in C# on a bitmap? Or are there any converting methods to convert the real pixel position in something DrawString needs?

推荐答案

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

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

您可以使用 GraphicsPath 而不是 DrawStringTextRenderer,因为它会让您知道它的网络边界矩形GraphicsPath.GetBounds() .

You can use a GraphicsPath instead of DrawString or TextRenderer, as it will let you know its net bounds rectangle with GraphicsPath.GetBounds() .

知道了之后,就可以使用 TranslateTransform 计算如何移动 Graphics 对象:

When you know it, you can calculate how to move the Graphics object using 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 small test routine to let us 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 );

}

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

The GetBounds method returns a RectangleF; in my example it is {X=0.09375, Y=6.0625, Width=21, Height=22.90625}. Do note that due to rounding things can always be off by one..

您可能想也可能不想将 Graphics 设置更改为特殊的 Smoothingmodes 等.

You may or may not want to change the Graphics setting to special Smoothingmodes etc..

还应注意,这将自动进行,即通过边界矩形进行机械居中.这可能与 'optical or视觉居中',这很难编码,并且在某种程度上是个人品味的问题.但排版既是一种职业,也是一种艺术..

Also it should be noted that this will do automatic ie mechanical centering by the bounds rectangle. This may be quite different from 'optical or visual centering', which is rather hard to code and to some extent a matter of personal taste. But typography is as much an art as a profession..

这篇关于如何在精确的像素位置绘制字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

ActiveDirectory error 0x8000500c when traversing properties(遍历属性时 ActiveDirectory 错误 0x8000500c)
search by samaccountname with wildcards(使用通配符按 samaccountname 搜索)
Get the list of Groups for the given UserPrincipal(获取给定 UserPrincipal 的组列表)
Can you find an Active Directory User#39;s Primary Group in C#?(你能在 C# 中找到 Active Directory 用户的主要组吗?)
How to register System.DirectoryServices for use in SQL CLR User Functions?(如何注册 System.DirectoryServices 以在 SQL CLR 用户函数中使用?)
Query From LDAP for User Groups(从 LDAP 查询用户组)