如何在精确的像素位置绘制一个字符串 [英] How to draw a string at an exact pixel position

查看:136
本文介绍了如何在精确的像素位置绘制一个字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在C#中将一个字符串(单个字符)绘制到一个位图中,位置如下:

 位图bmp =新的位图(64,64); 
Graphics g = Graphics.FromImage(bmp);
g.DrawString(W,font1,new SolidBrush(myColor),new Point(32,32);

在单个字母周围呈现出太多空白空间,我无法猜出需要的位置来绘制角色将它放在最后的正确位置。



现在我有了字符的像素精确尺寸(查看单独渲染的位图中的位)。但是,如果我无法在确切位置绘制字符(例如中心或者右上角或....)。

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

解决方案

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



您可以使用 GraphicsPath 而不是 DrawString TextRenderer ,因为它会让你知道它的网路界限s矩形 GraphicsPath.GetBounds()

当您知道它时,您可以使用 TranslateTransform来计算如何移动 Graphics 对象



 private void button1_Click(object sender,EventArgs e)
{
string text =Y; //无论
位图bmp =新位图(64,64); //无论
bmp.SetResolution(96,96); //无论
float fontSize = 32f; (GraphicsG = Graphics.FromImage(bmp))
using(GraphicsPath GP = new GraphicsPath())
using(FontFamily fontF = new FontFamily( Arial))
{
testPattern(g,bmp.Size); //可选

GP.AddString(text,fontF,0,fontSize,Point.Empty,
StringFormat.GenericTypographic);
//这是没有任何空格的净边界:
Rectangle br = Rectangle.Round(GP.GetBounds());

g.DrawRectangle(Pens.Red,br); //仅用于测试

//现在我们中心:
g.TranslateTransform((bmp.Width - br.Width)/ 2 - br.X,
(bmp。 Height - br.Height)/ 2 - br.Y);
//并填写
g.FillPath(Brushes.Black,GP);
g.ResetTransform();
}

//无论你想做什么..
pictureBox1.Image = bmp;
bmp.Save(D:\\__test.png,ImageFormat.Png);


$ / code>

一个小测试例程让我们看到更好的中心:

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

$ b

GetBounds 方法返回一个 RectangleF ;在我的例子中它是 {X = 0.09375,Y = 6.0625,宽度= 21,高度= 22.90625} 。请注意,由于四舍五入的东西总是可以关闭..



您可能会也可能不想要更改图形设置为特殊的 Smoothingmodes 等等。

另外应该注意的是,这会自动执行,即机械以边界矩形为中心。这可能与'optical或视觉对中'',这是相当难以编码,并在一定程度上是个人品味的问题。但印刷术与职业一样是一门艺术。

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

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..

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

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

}

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..

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

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..

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆