Dynamically Set FontPointSize for Text?

Magick.NET is an object-oriented C# interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning Magick.NET
Post Reply
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Dynamically Set FontPointSize for Text?

Post by GlennIM »

Please help... I'm desperate.

In my application I'm using a variety of Fonts by setting FontFamily variable, but I need the FontPointSize to change to fit into the dimensions of the image the text is written on. I tried calculating the FontPointSize using the code below but it doesn't really do the job.

Can anyone here show me what code I could use to get the right FontPointSize based on the FontFamily used and image size?

Thanks in Advance... Glenn

Code: Select all

       private int GetProperFontSize(MagickImage img)
        {
            var width = img.Width;

            if (width > 480 && width <= 680)
            {
                return 40;
            }

            if (width > 680 && width <= 800)
            {
                return 44;
            }

            if (width > 800 && width <= 1024)
            {
                return 52;
            }

            if (width > 1024 && width <= 1600)
            {
                return 64;
            }

            if (width > 1600 && width <= 2048)
            {
                return 70;
            }

            if (width > 2048 && width <= 2560)
            {
                return 86;
            }

            if (width > 2560 && width <= 6000)
            {
                return 100;
            }

            return 16;
        }
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Dynamically Set FontPointSize for Text?

Post by snibgo »

GlennIM wrote:... but it doesn't really do the job.
Can you be more specific?

Your code ignores the image resolution. This will cause problems unless all your images have the same resolution.
snibgo's IM pages: im.snibgo.com
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Re: Dynamically Set FontPointSize for Text?

Post by GlennIM »

Not sure what you mean by resolution. I am using a .JPG file for image modification.

Here is the code I use...

Code: Select all

int widthOfImage = GetProperFontSize(image);

var headerSnippetreadSettings = new MagickReadSettings()
 {
        FontFamily = FontFamily, // i.e. "Helvetica-Condensed-Light"
        FontPointsize = widthOfImage,
        FontWeight = FontWeight.Bold
 };
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Dynamically Set FontPointSize for Text?

Post by snibgo »

Resolution ties together the two systems of measuring length: pixels and inches (or centimetres). For example: 72 dpi (dots per inch).

One point is 1/72 inches, more or less. So a font size of 36 points will give a text height of 0.5 inches. But your image might be 72 dpi, so the text height is 36 pixels. Or it might be 720 dpi, so the text height is 360 pixels.
snibgo's IM pages: im.snibgo.com
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Re: Dynamically Set FontPointSize for Text?

Post by GlennIM »

I think each image will have a different resolution. Is there a way to force all the images I modify to be the same resolution?

If so can you tell me how I could change the GetProperFontSize(image) to calculate the proper FontPoinSize for the FontFamily used?
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Re: Dynamically Set FontPointSize for Text?

Post by GlennIM »

I also tried this code and it returns the wrong font point size...

Code: Select all

static public int MeasureDisplayStringWidth(Graphics graphics, string text, Font font)
        {
            System.Drawing.StringFormat format = new System.Drawing.StringFormat();
            System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0, 1000, 1000);
            System.Drawing.CharacterRange[] ranges = { new System.Drawing.CharacterRange(0, text.Length) };
            System.Drawing.Region[] regions = new System.Drawing.Region[1];

            format.SetMeasurableCharacterRanges(ranges);
            regions = graphics.MeasureCharacterRanges(text, font, rect, format);
            rect = regions[0].GetBounds(graphics);

            return (int)(rect.Right + 1.0f);
        }

        FontFamily ff = new FontFamily(FontFamilyStr);
        Font f = new Font(ff,12);
        Image imageFile = Image.FromFile(imgURL); // image magick image
        Graphics newGraphics = Graphics.FromImage(imageFile);
        int fps = MeasureDisplayStringWidth(newGraphics, "This is a String To Use, f);

         var headerSnippetreadSettings = new MagickReadSettings()
         {
                        FontFamily = FontFamilyStr, // i.e Helvetica-Condensed-Light
                        FontPointsize = fps,
                        FontWeight = FontWeight.Bold
         };
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Dynamically Set FontPointSize for Text?

Post by dlemstra »

Do you have a specific area in image where you want to write the text depending on the size of the image? Can you explain in a bit more detail what you are trying to accomplish?
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Re: Dynamically Set FontPointSize for Text?

Post by GlennIM »

Here is the test image where you can see the text does not size properly inside the rounded corner image on the top and bottom. The code I wrote is below.

Image

Yes. Here is the sample code below that produces the image above. Please tell me how I can resize the text within the bounds of the rounded corner image on top and bottom. Any help is much appreciated.

Code: Select all

private void TextOnImage()
        {
            var image = new MagickImage(MagickColors.Red, 1000, 1000);

            MagickImage imageresult;
            MagickImage modimage;

            try
            {
                using (var images = new MagickImageCollection())
                {
                    int widthOfImage = GetProperFontSize(image);

                    var headerSnippetreadSettings = new MagickReadSettings()
                    {
                        BackgroundColor = MagickColors.LightBlue,
                        FontFamily = "Showcard Gothic",
                        FontPointsize = widthOfImage,
                        FillColor = MagickColors.Black,
                        FontWeight = FontWeight.Bold
                    };

                    // This will make the background of the label Khaki.
                    var readSettings = new MagickReadSettings()
                    {
                        BackgroundColor = MagickColors.LightBlue,
                        FontFamily = "Helvetica-Condensed-Light", // -font Helvetica-Condensed-Light
                        FontPointsize = widthOfImage, // -pointsize
                        FillColor = MagickColors.Black,
                        FontWeight = FontWeight.Bold
                    };

                    // Create the label image.
                    var branding = new MagickImage("label:MyDomain.com", readSettings);

                    // Create the label image.
                    var topheading = new MagickImage("label:Our Site Is Full of Great Cooking Tips", headerSnippetreadSettings);

                    // Create the label image.
                    var bottomheading = new MagickImage("label:Great Cooking Tips From Our Kitchen to Your Table", headerSnippetreadSettings);

                    branding.Extent(image.Width, 100, Gravity.Center);

                    topheading.Extent(image.Width, 100, Gravity.Center);

                    bottomheading.Extent(image.Width, 100, Gravity.Center);

                    // add the images to the collection
                    images.Add(topheading);
                    images.Add(image);
                    images.Add(bottomheading);
                    images.Add(branding);

                    // Append the images to create the output image.
                    using (var result = images.AppendVertically())
                    {
                        imageresult = new MagickImage(result);

                        // imageresult gets disposed of in the rounding code below, so need to write the imageresult to a new image
                        modimage = new MagickImage(imageresult);
                    }
                }

                using (imageresult)
                {
                    using (var mask = new MagickImage(MagickColors.White, imageresult.Width, imageresult.Height))
                    {
                        var size = 150;

                        new ImageMagick.Drawables()
                            .FillColor(MagickColors.Black)
                            .StrokeColor(MagickColors.Black)
                            .Polygon(new PointD(0, 0), new PointD(0, size), new PointD(size, 0))
                            .Polygon(new PointD(mask.Width, 0), new PointD(mask.Width, size), new PointD(mask.Width - size, 0))
                            .Polygon(new PointD(0, mask.Height), new PointD(0, mask.Height - size), new PointD(size, mask.Height))
                            .Polygon(new PointD(mask.Width, mask.Height), new PointD(mask.Width, mask.Height - size), new PointD(mask.Width - size, mask.Height))
                            .FillColor(MagickColors.White)
                            .StrokeColor(MagickColors.White)
                            .Circle(size, size, size, 0)
                            .Circle(mask.Width - size, size, mask.Width - size, 0)
                            .Circle(size, mask.Height - size, 0, mask.Height - size)
                            .Circle(mask.Width - size, mask.Height - size, mask.Width - size, mask.Height)
                            // .BorderColor(MagickColors.Red)
                            .Draw(mask);

                        // This copies the pixels that were already transparent on the mask.
                        using (var imageAlpha = imageresult.Clone())
                        {
                            imageAlpha.Alpha(AlphaOption.Extract);
                            imageAlpha.Opaque(MagickColors.White, MagickColors.None);
                            mask.Composite(imageAlpha, CompositeOperator.Over);
                        }

                        mask.HasAlpha = false;
                        imageresult.HasAlpha = false;
                        imageresult.Composite(mask, CompositeOperator.CopyAlpha);

                        // imageresult gets disposed of so need to write the imageresult to a new image
                        modimage = new MagickImage(imageresult);
                    }
                 }

                modimage.Write(@"D:\TestImage.png");
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private int GetProperFontSize(MagickImage img)
        {
            var width = img.Width;

            if (width > 480 && width <= 680)
            {
                return 40;
            }

            if (width > 680 && width <= 800)
            {
                return 44;
            }

            if (width > 800 && width <= 1024)
            {
                return 52;
            }

            if (width > 1024 && width <= 1600)
            {
                return 64;
            }

            if (width > 1600 && width <= 2048)
            {
                return 70;
            }

            if (width > 2048 && width <= 2560)
            {
                return 86;;
            }

            if (width > 2560 && width <= 6000)
            {
                return 100;
            }

            return 16;
        }
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Dynamically Set FontPointSize for Text?

Post by dlemstra »

You can use `Width` instead of `FontPointsize` to set the desired width of your label.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
GlennIM
Posts: 23
Joined: 2018-07-22T22:22:12-07:00
Authentication code: 1152

Re: Dynamically Set FontPointSize for Text?

Post by GlennIM »

Thank you SO much. I set the Width to the width of the image minus a little to give some padding and it works.

I'm curious, what does setting the Width actually do? Does it "scale" the text?

-Glenn
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Dynamically Set FontPointSize for Text?

Post by dlemstra »

Setting the Width makes sure that the text is scaled to fit inside the specified Width. You probably want to set both the Width and the Height in your case. This will make sure it fits inside that area. And with the `TextGravity` you can determine where the text is positioned. It looks like you want to center the text so you should probably use Gravity.Center there.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
Post Reply