关闭抗锯齿以在 WPF 中绘制位图
Turn off anti-aliasing for drawing to bitmap in WPF
我使用 WPF 将文本渲染为位图。我想关闭抗锯齿功能,我的意思是我希望像素为白色或黑色。但文字仍然模糊,有些像素甚至是灰色的。
这是我的代码。有些行可能不需要。
RenderTargetBitmap bm = new RenderTargetBitmap(bitmapWidth, bitmapHeight, dpiX, dpiY, PixelFormats.Pbgra32);
DrawingVisual drawing_visual = new DrawingVisual();
RenderOptions.SetEdgeMode(drawing_visual, EdgeMode.Unspecified);
RenderOptions.SetBitmapScalingMode(drawing_visual, BitmapScalingMode.Linear);
RenderOptions.SetEdgeMode(bm, EdgeMode.Unspecified);
RenderOptions.SetBitmapScalingMode(bm, BitmapScalingMode.Linear);
DrawingContext drawing_context = drawing_visual.RenderOpen();
FormattedText ft = new FormattedText("my text", CultureInfo.InvariantCulture, System.Windows.FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black);
drawing_context.DrawText(ft, new Point(0, 0));
drawing_context.Close();
bm.Render(drawing_visual);
渲染图像:
要查看解决方案,您可以从GitHub:
下载源代码
https://github.com/qub1n/Font-rendering.git
这里的重要概念是 TextRenderingMode. It's logical, since you don't want anti-aliased text, you must set the TextRenderingMode to Aliased。难的是放在哪里...
我建议您像这样创建一个 DrawingImage 作为起始对象(将其用作您的 canvas 源,而不是位图):
public static DrawingImage CreateImage(int heightPixel, Typeface typeface, double fontSize, string text)
{
var group = new DrawingGroup();
using (var context = group.Open())
{
var ft = new FormattedText(text, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black, null,
TextFormattingMode.Display); // this is the important line here!
context.DrawText(ft, new Point(0, 0));
}
return new DrawingImage(group);
}
注意同样重要的 TextFormattingMode value set to Display. If you don't do this and keep the default value (Ideal),那么你仍然会有抗锯齿功能。
现在,为了在显示器上呈现,您必须在 Visual 元素上使用 TextRenderingMode,因此在您的示例中,在您的 canvas 元素上:
<controls:ImageCanvas ... TextOptions.TextRenderingMode="Aliased" ... />
要在位图上渲染,您必须创建一个中间视觉对象,这里是一个 Image 对象,因此您可以在其上应用 TextRenderingMode:
public static void SaveToFile(string filePath, DrawingImage drawing)
{
var image = new Image { Source = drawing };
image.Arrange(new Rect(new Size(drawing.Width, drawing.Height)));
// this is the important line here!
TextOptions.SetTextRenderingMode(image, TextRenderingMode.Aliased);
// note if you use a different DPI than the screen (96 here), you still will have anti-aliasing
// as the system is pretty automatic anyway
var bitmap = new RenderTargetBitmap((int)drawing.Width, (int)drawing.Height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(image);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(fileStream);
}
}
原来在drawinVisual
上设置TextOptions.SetTextRenderingMode()
是不行的。已接受的答案在生成的位图中仍然存在锯齿问题(使用 TextFormattingMode.Display
效果更好,但仍未完全消除锯齿)。
对我有用的是在绘图视觉上设置内部 属性:
var visual = new DrawingVisual();
var property = typeof(Visual).GetProperty("VisualTextRenderingMode",
BindingFlags.NonPublic | BindingFlags.Instance);
property.SetValue(visual, TextRenderingMode.Aliased);
我使用 WPF 将文本渲染为位图。我想关闭抗锯齿功能,我的意思是我希望像素为白色或黑色。但文字仍然模糊,有些像素甚至是灰色的。
这是我的代码。有些行可能不需要。
RenderTargetBitmap bm = new RenderTargetBitmap(bitmapWidth, bitmapHeight, dpiX, dpiY, PixelFormats.Pbgra32);
DrawingVisual drawing_visual = new DrawingVisual();
RenderOptions.SetEdgeMode(drawing_visual, EdgeMode.Unspecified);
RenderOptions.SetBitmapScalingMode(drawing_visual, BitmapScalingMode.Linear);
RenderOptions.SetEdgeMode(bm, EdgeMode.Unspecified);
RenderOptions.SetBitmapScalingMode(bm, BitmapScalingMode.Linear);
DrawingContext drawing_context = drawing_visual.RenderOpen();
FormattedText ft = new FormattedText("my text", CultureInfo.InvariantCulture, System.Windows.FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black);
drawing_context.DrawText(ft, new Point(0, 0));
drawing_context.Close();
bm.Render(drawing_visual);
渲染图像:
要查看解决方案,您可以从GitHub:
下载源代码https://github.com/qub1n/Font-rendering.git
这里的重要概念是 TextRenderingMode. It's logical, since you don't want anti-aliased text, you must set the TextRenderingMode to Aliased。难的是放在哪里...
我建议您像这样创建一个 DrawingImage 作为起始对象(将其用作您的 canvas 源,而不是位图):
public static DrawingImage CreateImage(int heightPixel, Typeface typeface, double fontSize, string text)
{
var group = new DrawingGroup();
using (var context = group.Open())
{
var ft = new FormattedText(text, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black, null,
TextFormattingMode.Display); // this is the important line here!
context.DrawText(ft, new Point(0, 0));
}
return new DrawingImage(group);
}
注意同样重要的 TextFormattingMode value set to Display. If you don't do this and keep the default value (Ideal),那么你仍然会有抗锯齿功能。
现在,为了在显示器上呈现,您必须在 Visual 元素上使用 TextRenderingMode,因此在您的示例中,在您的 canvas 元素上:
<controls:ImageCanvas ... TextOptions.TextRenderingMode="Aliased" ... />
要在位图上渲染,您必须创建一个中间视觉对象,这里是一个 Image 对象,因此您可以在其上应用 TextRenderingMode:
public static void SaveToFile(string filePath, DrawingImage drawing)
{
var image = new Image { Source = drawing };
image.Arrange(new Rect(new Size(drawing.Width, drawing.Height)));
// this is the important line here!
TextOptions.SetTextRenderingMode(image, TextRenderingMode.Aliased);
// note if you use a different DPI than the screen (96 here), you still will have anti-aliasing
// as the system is pretty automatic anyway
var bitmap = new RenderTargetBitmap((int)drawing.Width, (int)drawing.Height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(image);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(fileStream);
}
}
原来在drawinVisual
上设置TextOptions.SetTextRenderingMode()
是不行的。已接受的答案在生成的位图中仍然存在锯齿问题(使用 TextFormattingMode.Display
效果更好,但仍未完全消除锯齿)。
对我有用的是在绘图视觉上设置内部 属性:
var visual = new DrawingVisual();
var property = typeof(Visual).GetProperty("VisualTextRenderingMode",
BindingFlags.NonPublic | BindingFlags.Instance);
property.SetValue(visual, TextRenderingMode.Aliased);