#c# #.net #bitmap #character
#c# #.net #растровое изображение #символ
Вопрос:
Я создал текстуру (растровое изображение), которая используется для рисования произвольных чисел
Текстура содержит текст: 0123456789.-
Теперь мне нужны координаты каждого символа.
TextRenderer.MeasureText(c.ToString(), m_font, new Size(1, 1), TextFormatFlags.NoPadding);
… возвращает значение 16×17
g.MeasureString(c.ToString(), m_font);
…возвращает значение 11.9×17.7
Фактический размер 8×11
Мой обходной путь на данный момент — это ручное измерение каждого символа, которое дает следующую таблицу:
coords.Add('0', new RectangleF(1, 3, 8, 11));
coords.Add('1', new RectangleF(9, 3, 7, 11));
coords.Add('2', new RectangleF(15, 3, 8, 11));
coords.Add('3', new RectangleF(22, 3, 8, 11));
coords.Add('4', new RectangleF(29, 3, 8, 11));
coords.Add('5', new RectangleF(36, 3, 8, 11));
coords.Add('6', new RectangleF(43, 3, 8, 11));
coords.Add('7', new RectangleF(50, 3, 8, 11));
coords.Add('8', new RectangleF(57, 3, 8, 11));
coords.Add('9', new RectangleF(64, 3, 8, 11));
coords.Add('.', new RectangleF(72, 3, 3, 11));
coords.Add('-', new RectangleF(75, 3, 6, 11));
Я хотел бы использовать динамический шрифт, поэтому требуется программный способ измерения размера.
Комментарии:
1. я думаю, вам придется искать больше перегрузок. представьте, что вы пытаетесь измерить i. откуда вы знаете, что точка является частью i, а не отдельным символом. Возможно, вы получаете неожиданные значения, потому что они также включают высоту строки при вызове функции.
Ответ №1:
Укажите методу MeasureString для работы с общим типографским строковым форматом.
static void Main(string[] args)
{
var image = new Bitmap(1000, 500);
var g = Graphics.FromImage(image);
g.FillRectangle(System.Drawing.Brushes.White, 0, 0, 1000, 500);
var stringFormat = new StringFormat(StringFormat.GenericTypographic) {
Alignment = StringAlignment.Near,
FormatFlags = System.Drawing.StringFormatFlags.LineLimit | System.Drawing.StringFormatFlags.NoClip | StringFormatFlags.DirectionRightToLeft
};
var font = new Font(new System.Drawing.FontFamily("Times New Roman"), 72.0f,FontStyle.Regular, GraphicsUnit.Point);
var point = new PointF { X = 10, Y = 10 };
SizeF[] outputs = new SizeF[7];
SizeF[] total = new SizeF[7];
outputs[0] = g.MeasureString("T", font, point, stringFormat);
outputs[1] = g.MeasureString("e", font, point, stringFormat);
outputs[2] = g.MeasureString("s", font, point, stringFormat);
outputs[3] = g.MeasureString("t", font, point, stringFormat);
outputs[4] = g.MeasureString("S", font, point, stringFormat);
outputs[5] = g.MeasureString("t", font, point, stringFormat);
outputs[6] = g.MeasureString("r", font, point, stringFormat);
total[0] = g.MeasureString("T", font, point, stringFormat);
total[1] = g.MeasureString("Te", font, point, stringFormat);
total[2] = g.MeasureString("Tes", font, point, stringFormat);
total[3] = g.MeasureString("Test", font, point, stringFormat);
total[4] = g.MeasureString("TestS", font, point, stringFormat);
total[5] = g.MeasureString("TestSt", font, point, stringFormat);
total[6] = g.MeasureString("TestStr", font, point, stringFormat);
stringFormat.FormatFlags = System.Drawing.StringFormatFlags.LineLimit | System.Drawing.StringFormatFlags.NoClip;
g.DrawString("TestStr", font, System.Drawing.Brushes.Red, new PointF { X = 10, Y = 10 }, stringFormat);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 0), 10.0f, outputs[0].Width, outputs[0].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 1), 10.0f, outputs[1].Width, outputs[1].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 2), 10.0f, outputs[2].Width, outputs[2].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 3), 10.0f, outputs[3].Width, outputs[3].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 4), 10.0f, outputs[4].Width, outputs[4].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 5), 10.0f, outputs[5].Width, outputs[5].Height);
g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue, 1.0f), GetOutputPositionX(total,outputs, 6), 10.0f, outputs[6].Width, outputs[6].Height);
image.Save(@"c:Tempbla.png");
}
private static float GetOutputPositionX(SizeF[] total, SizeF[] outputs, int p)
{
return 10.0f total[p].Width - outputs[p].Width;
}
Чтобы получить точную позицию, из-за этих перекрывающихся символов вам нужно вычислить ширину буквы «e» и общую ширину буквы «Te».
Кроме того, очевидно, что в функции MeasureString есть ошибка. Если вы вызываете MeasureString без StringFormatFlags .DirectionRightToLeft перекрытие символов «Te» игнорируется.
Комментарии:
1. Я не могу заставить это работать. Я взял точный код и поместил его в новое решение, но выравнивание зеленой сетки в моем случае неверно. Не могли бы вы проверить еще раз?
2. @testalino Не могли бы вы добавить свое выходное изображение.
3. @testalino Я уже тестировал в приложении WPF, и оно работало нормально. В консольном приложении GDI перекрывает символы «Te». Чего по какой-либо причине не происходит в приложении WPF. Я обновил свой код. Теперь должно сработать.
4. Хорошо, большое вам спасибо за работу, которую вы вложили в это. Я могу получить тот же результат, что и вы, при использовании вашего кода. Хотя в моей среде это все еще не работает, потому что, когда вы уменьшаете размер шрифта, рамка внезапно перестает соответствовать буквам, возможно, из-за округления до пикселей. Это особенно актуально при использовании моего фактического шрифта (Tahoma, 10): i.imgur.com/egBQLn6.png