2015-10-15 72 views
2

我嘗試用一​​個確切的位置繪製在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所需的實際像素位置?

+0

你在尋找Graphics.MeasureString/MEasureCharRanges它將計算邊界矩形? –

+0

在繪製之前它能幫助你[測量字符串](https://msdn.microsoft.com/library/6xe5hazb.aspx)嗎? – Corak

+0

您可以使用GraphicsPath獲取所有像素的測量值。但它不會告訴你這個邊界框在DrawString的邊界框中。所以,也許你需要真正使用GP本身.. – TaW

回答

2

無需看像素或開始自己的字體工作..

您可以使用GraphicsPath代替DrawStringTextRenderer,因爲它會讓你知道它的淨邊界矩形GraphicsPath.GetBounds()

當你知道它,你可以計算出如何使用TranslateTransform移動Graphics對象:

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'完全不同,這很難編碼,並且在某種程度上是個人品味的問題。但排版是一種藝術作爲一種職業..

相關問題