将非常高质量的文本呈现为位图
render very high quality text to bitmap
我想在图片上添加一些文字。这是我的方法:
private Bitmap ConvertTextToImage(string text, FontFamily fontFamily, float fontSize, FontStyle fontStyle = FontStyle.Regular,
StringFormat stringFormat = default, float MaxWidth = float.MaxValue, float MaxHeight = float.MaxValue, Color backgroundColor = default, Color foregroundColor = default)
{
Bitmap bitmap = new Bitmap(1, 1);
Graphics graphics = Graphics.FromImage(bitmap);
if (stringFormat == default) stringFormat = new StringFormat();
if (backgroundColor == default) backgroundColor = Color.Transparent;
if (foregroundColor == default) foregroundColor = Color.Black;
Font font = new Font(fontFamily, fontSize, fontStyle);
SizeF stringSize = graphics.MeasureString(text, font, int.MaxValue, stringFormat);
while (stringSize.Width > MaxWidth || stringSize.Height > MaxHeight)
{
fontSize -= (float)0.1;
font = new Font(fontFamily, fontSize, fontStyle);
stringSize = graphics.MeasureString(text, font, int.MaxValue, stringFormat);
}
bitmap = new Bitmap((int)stringSize.Width, (int)stringSize.Height);
graphics = Graphics.FromImage(bitmap);
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
graphics.Clear(backgroundColor);
int x = 0;
if (stringFormat.FormatFlags == StringFormatFlags.DirectionRightToLeft && stringFormat.Alignment == StringAlignment.Center)
x = (int)stringSize.Width / 2;
else if (stringFormat.FormatFlags == StringFormatFlags.DirectionRightToLeft) x = (int)stringSize.Width;
else if (stringFormat.Alignment == StringAlignment.Center) x += (int)stringSize.Width / 2;
graphics.DrawString(text, font, new SolidBrush(foregroundColor), x, 0, stringFormat);
return bitmap;
}
//...
适用于大字体或简单字体(例如 Samim)。但是对于小尺寸的复杂字体(IranNastaliq),它会变成这样(棕色在主图像上,黑色由 C# 生成):
所以我决定使用 GraphicsPath.AddString
而不是 Graphics.DrawString
:
GraphicsPath graphicsPath = new GraphicsPath();
//...
graphicsPath.AddString(text, fontFamily, (int)fontStyle, fontSize * graphics.DpiY / 72, new Point(x, 0), stringFormat);
graphics.FillPath(new SolidBrush(foregroundColor), graphicsPath);
但是结果还是不好:
如何呈现更高质量的文本?图片分辨率为2480x3508x300dpi,字体大小约为13.
感谢TaW的评论,问题解决了。我应该调整位图分辨率 (DPI) 以匹配原始图片的分辨率。这是正确的代码:
private Bitmap ConvertTextToImage(string text, FontFamily fontFamily, float fontSize,
FontStyle fontStyle = FontStyle.Regular, StringFormat stringFormat = default,
float MaxWidth = float.MaxValue, float MaxHeight = float.MaxValue, float xDpi = 72, float yDpi = 72,
Color backgroundColor = default, Color foregroundColor = default)
{
//...
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
bitmap.SetResolution(xDpi,yDpi);
//...
graphics.DrawString(text, font, new SolidBrush(foregroundColor), x, 0, stringFormat);
}
private void Write()
{
//...
Bitmap name = ConvertTextToImage(Name.Text, IranNastaliq, 58, MaxWidth: 525, xDpi: 300, yDpi: 300);
graphics.DrawImage(name, new Point(1104, 1700));
//...
bitmap.Save("img.jpg", ImageFormat.Jpeg);
}
结果(黑色文字由GDI绘制):
我想在图片上添加一些文字。这是我的方法:
private Bitmap ConvertTextToImage(string text, FontFamily fontFamily, float fontSize, FontStyle fontStyle = FontStyle.Regular,
StringFormat stringFormat = default, float MaxWidth = float.MaxValue, float MaxHeight = float.MaxValue, Color backgroundColor = default, Color foregroundColor = default)
{
Bitmap bitmap = new Bitmap(1, 1);
Graphics graphics = Graphics.FromImage(bitmap);
if (stringFormat == default) stringFormat = new StringFormat();
if (backgroundColor == default) backgroundColor = Color.Transparent;
if (foregroundColor == default) foregroundColor = Color.Black;
Font font = new Font(fontFamily, fontSize, fontStyle);
SizeF stringSize = graphics.MeasureString(text, font, int.MaxValue, stringFormat);
while (stringSize.Width > MaxWidth || stringSize.Height > MaxHeight)
{
fontSize -= (float)0.1;
font = new Font(fontFamily, fontSize, fontStyle);
stringSize = graphics.MeasureString(text, font, int.MaxValue, stringFormat);
}
bitmap = new Bitmap((int)stringSize.Width, (int)stringSize.Height);
graphics = Graphics.FromImage(bitmap);
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
graphics.Clear(backgroundColor);
int x = 0;
if (stringFormat.FormatFlags == StringFormatFlags.DirectionRightToLeft && stringFormat.Alignment == StringAlignment.Center)
x = (int)stringSize.Width / 2;
else if (stringFormat.FormatFlags == StringFormatFlags.DirectionRightToLeft) x = (int)stringSize.Width;
else if (stringFormat.Alignment == StringAlignment.Center) x += (int)stringSize.Width / 2;
graphics.DrawString(text, font, new SolidBrush(foregroundColor), x, 0, stringFormat);
return bitmap;
}
//...
适用于大字体或简单字体(例如 Samim)。但是对于小尺寸的复杂字体(IranNastaliq),它会变成这样(棕色在主图像上,黑色由 C# 生成):
所以我决定使用 GraphicsPath.AddString
而不是 Graphics.DrawString
:
GraphicsPath graphicsPath = new GraphicsPath();
//...
graphicsPath.AddString(text, fontFamily, (int)fontStyle, fontSize * graphics.DpiY / 72, new Point(x, 0), stringFormat);
graphics.FillPath(new SolidBrush(foregroundColor), graphicsPath);
但是结果还是不好:
如何呈现更高质量的文本?图片分辨率为2480x3508x300dpi,字体大小约为13.
感谢TaW的评论,问题解决了。我应该调整位图分辨率 (DPI) 以匹配原始图片的分辨率。这是正确的代码:
private Bitmap ConvertTextToImage(string text, FontFamily fontFamily, float fontSize,
FontStyle fontStyle = FontStyle.Regular, StringFormat stringFormat = default,
float MaxWidth = float.MaxValue, float MaxHeight = float.MaxValue, float xDpi = 72, float yDpi = 72,
Color backgroundColor = default, Color foregroundColor = default)
{
//...
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
bitmap.SetResolution(xDpi,yDpi);
//...
graphics.DrawString(text, font, new SolidBrush(foregroundColor), x, 0, stringFormat);
}
private void Write()
{
//...
Bitmap name = ConvertTextToImage(Name.Text, IranNastaliq, 58, MaxWidth: 525, xDpi: 300, yDpi: 300);
graphics.DrawImage(name, new Point(1104, 1700));
//...
bitmap.Save("img.jpg", ImageFormat.Jpeg);
}
结果(黑色文字由GDI绘制):