Page 1 of 1

Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T05:44:09-07:00
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;
        }

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T06:48:41-07:00
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.

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T07:22:28-07:00
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
 };

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T07:28:24-07:00
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.

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T08:17:33-07:00
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?

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-19T11:39:14-07:00
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
         };

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-20T14:36:06-07:00
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?

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-21T19:25:48-07:00
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;
        }

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-25T08:31:35-07:00
by dlemstra
You can use `Width` instead of `FontPointsize` to set the desired width of your label.

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-25T12:02:43-07:00
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

Re: Dynamically Set FontPointSize for Text?

Posted: 2018-08-26T03:28:00-07:00
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.