【问题标题】:Turn off anti-aliasing for drawing to bitmap in WPF关闭抗锯齿以在 WPF 中绘制位图
【发布时间】:2017-05-10 07:35:22
【问题描述】:

我使用 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

【问题讨论】:

  • 文本值得使用 WPF 进行特殊处理。也许您应该尝试 TextOptions.TextFormattingMode 和/或 TextRenderingMode:blogs.msdn.microsoft.com/text/2009/08/24/…
  • TextFormattingMode 没有解决它并且 TextRenderingMode 不包含没有抗锯齿的设置。
  • 您对屏幕可视化或位图(.png 等文件)创建感兴趣吗?它们完全不同。
  • 尤其是位图,我要导出。
  • 如何将EdgeMode 设置为Aliased

标签: wpf drawing antialiasing


【解决方案1】:

这里的重要概念是TextRenderingMode。这是合乎逻辑的,因为您不想要抗锯齿文本,您必须将 TextRenderingMode 设置为 Aliased。难的是放在哪里...

我建议你创建一个 DrawingImage,像这样,作为起始对象(使用它作为你的画布源,而不是位图):

    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 值设置为Display。如果您不这样做并保留默认值 (Ideal),那么您仍然会有抗锯齿功能。

现在,为了在显示器上进行渲染,您必须在 Visual 元素上使用 TextRenderingMode,因此在您的示例中,在您的画布元素上:

    <controls:ImageCanvas ... TextOptions.TextRenderingMode="Aliased" ... />

为了在位图上进行渲染,您必须创建一个中间 Visual,这里是一个 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);
        }
    }

【讨论】:

    【解决方案2】:

    事实证明,在drawinVisual 上设置TextOptions.SetTextRenderingMode() 不起作用。接受的答案在生成的位图中仍然存在混叠问题(最好使用TextFormattingMode.Display,但仍不能完全消除混叠)。

    对我有用的是在绘图视觉上设置内部属性:

    
        var visual = new DrawingVisual();
        var property = typeof(Visual).GetProperty("VisualTextRenderingMode", 
                    BindingFlags.NonPublic | BindingFlags.Instance);
    
        property.SetValue(visual, TextRenderingMode.Aliased);
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      • 2010-11-19
      相关资源
      最近更新 更多