Пользовательская строка меры в C# без Graphics.MeasureString

Я пытаюсь создать изображение с заголовком/текстом для Youtube-Thumbnails.

Определены следующие правила:

  • Текст является заголовком видео и всегда меняется с миниатюры на миниатюру.
  • Porgram использует предопределенную ширину текста, которая не должна касаться текста на изображении.
  • Текст должен быть как можно ближе к предварительно определенному.

Поэтому я думал, что буду использовать Graphics.MeasureStringчтобы иметь возможность отслеживать ширину строки на изображении, увеличивать размер шрифта и повторять это до тех пор, пока предварительно определенная ширина не будет близко достигнута, но не затронута.

Но я проверил это с MeasureStringи обнаружил, что это не так точно. А также нашел подтверждение здесь: Graphics.MeasureCharacterRanges дает неправильные расчеты размера

Я пробовал то, что они рекомендовали, но безуспешно, так как окончательная ширина моей строки всегда переполняла границы изображения. Даже если моя предварительно определенная ширина была намного меньше, чем ширина изображения. (Ширина изображения: 1920; заданная ширина: 1600)

Поэтому мне пришла в голову идея создать собственный метод измерения и записать строку так, как я хочу, на новом растровом изображении и подсчитать максимальное количество пикселей строки по высоте и ширине. (Высота предназначена только для будущих вещей)

Мой текущий код:

      public static SizeF MeasuredStringSize(string text, Bitmap originBitmap, FontFamily fontFamily, StringFormat strformat)
{
    int currentFontSize = 10;
    SizeF measuredSize = new();

    var highestWidth = 0;
    var highestHeight = 0;



    while (highestWidth < maximumTextWidth)
    {

        Bitmap bitmap = new(originBitmap);
        Bitmap _bitmap = new(bitmap.Width, bitmap.Height);
        using Graphics graphics = Graphics.FromImage(bitmap);

        if (graphics != null)
        {
            graphics.TranslateTransform(bitmap.Width / 2, bitmap.Height / 2);

            currentFontSize++;
            graphics.Clear(Color.White);

            using GraphicsPath path = new();
            using SolidBrush brush = new(Color.Red);
            using Pen pen = new(Color.Red, 6)
            {
                LineJoin = LineJoin.Round
            };

            path.AddString(text, fontFamily, (int)fontStyle, currentFontSize, new Point(0, 0), strformat);
            graphics.DrawPath(pen, path);
            graphics.FillPath(brush, path);

            Dictionary<int, List<int>> redPixelMatrix = new();

            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    var currentPixelColor = bitmap.GetPixel(i, j);

                    if (currentPixelColor.B != 255 && currentPixelColor.G != 255 && currentPixelColor.R == 255)
                    {
                        if (!redPixelMatrix.ContainsKey(i))
                        {
                            redPixelMatrix.Add(i, new());
                        }

                        redPixelMatrix[i].Add(j);
                    }
                }
            }

            highestWidth = redPixelMatrix.Keys.Count;
            highestHeight = redPixelMatrix.Aggregate((l, r) => l.Value.Count > r.Value.Count ? l : r).Value.Count;

            Console.WriteLine($"X:{highestWidth};Y:{highestHeight}");

            //Debugging the final Image with Text to see the Result
            bitmap.Save(ResultPath);

        }
    }
    
    measuredSize = new SizeF(highestWidth, highestHeight);
    return measuredSize;
}

Результирующее изображение из bitmap.Save(ResultPath);когда строка достигает границ изображения, выглядит так:

Но точная ширина строки 1742вместо ширины моего изображения 1920который должен быть более или менее таким же в этот момент.

Итак, почему текст почти такой же ширины, как изображение, но не имеет такой же ширины?

0 ответов

Другие вопросы по тегам