1

I need to generate a single image, with a single character (letter) in it, which completely fills the image. I found a Bitmap.MeasureString option.

So what I tried to do was measure the size the string would be using this function, and then resizing the image to match, and then draw the letter.

But I am getting loads of white space all around the letter. I need the border of the image to be on the edges of the letter.

So a W would be a wide image, but an I would be a very narrow image.

I drew a line from the top left to bottom right to show what's happening.

enter image description here

Can you spot an issue with my code? Am I maybe misunderstanding this function? Or, it doesn't work as I'd hoped?

In the example image I posted, I want the top border of the image to be on the top border of the A. And the left border touching the bottom right hand of the A. And the bottom being right on the bottom edge of the A.

Here's what I am trying:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;

namespace SpikeFontToImage
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap source = new Bitmap(1, 1);
            Bitmap destination;

            Font stringFont = new Font("Tohoma", 1024);
            string text = "A";

            using (var measure = Graphics.FromImage(source))
            {
                var size = measure.MeasureString(text, stringFont);
                Console.WriteLine($"{text} is {size} in size");

                destination = new Bitmap( (int)size.Width, (int)size.Height);
                RectangleF rectf = new RectangleF(0, 0, destination.Width, destination.Height);
                StringFormat format = new StringFormat()
                {
                    Alignment = StringAlignment.Center,
                    LineAlignment = StringAlignment.Center
                };

                //RectangleF rectf = new RectangleF(70, 90, 90, 50);

                Graphics g = Graphics.FromImage(destination);

                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                g.DrawString(text, stringFont, Brushes.Black, rectf, format);

                Pen pen = new Pen(Color.GreenYellow, 3);
                g.DrawLine(pen, new Point(0, 0), new Point((int)size.Width, (int)size.Height));

                g.Flush();

                destination.Save(@"c:\temp\ccl.jpg");
            }

        }
    }
}
Craig
  • 18,074
  • 38
  • 147
  • 248
  • have you tried with the `StringFormat.GenericTypographic` option. Also i think you will always get a slightly larger size. you might just need to factor a fudge in – TheGeneral Oct 12 '20 at 06:28
  • 1
    See the notes and sample code here: [Remove top and bottom padding from Text drawn on an Image](https://stackoverflow.com/a/54383828/7444103) – Jimi Oct 12 '20 at 07:36
  • That was close @Jimi - But it trims pixels with the letter A, and if you render just a 1, or crops the character in half. I had high hope, based on the examples the provided. So close. Closer than mine. But not sure why it's cropping characters. – Craig Oct 12 '20 at 08:11
  • As commented on the original post: a single char may give a different result when measured using the Graphics (and GraphicsPath) object (`GraphicsPath.GetBounds()` may not include the padding), we usually measure at least two chars (for example, when you have to measure the width of a white char). [MeasureCharacterRanges](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.measurecharacterranges) can be use instead, to get a char's drawing box. I'll give a look to the original code. – Jimi Oct 12 '20 at 08:17
  • 1
    I could repro the results you're mentioning (thanks for noticing): `GraphicsPath.GetBounds()` doesn't measure a single *slim* char the same way, the drawing box can be clipped. I've changed the code, see whether you have better results. See also this method, using `Graphics.MeasureCharacterRanges`: [How to compute the correct width of a digit in pixels?](https://stackoverflow.com/a/54772134/7444103) – Jimi Oct 12 '20 at 09:14
  • Thanks Jimi - you gave me the answer. – Craig Oct 15 '20 at 07:01

0 Answers0