See the question and my original answer on StackOverflow

The important notion here is the TextRenderingMode. It's logical, since you don't want anti-aliased text, you must set the TextRenderingMode to Aliased. The difficulty is where to put it...

I recommend you create a DrawingImage instead, like this, as the start object (use it as your canvas source, instead of a bitmap):

    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);

Note the also important TextFormattingMode value set to Display. If you don't do this and keep the default value (Ideal), then you'll still have anti-aliasing.

Now, for rendering on the display, you will have to use TextRenderingMode on a Visual element, so in your example, on your canvas element:

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

and for rendering on a bitmap, you'll have to create an intermediary Visual, here an Image object, so you can apply the TextRenderingMode on it:

    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);

        using (var fileStream = new FileStream(filePath, FileMode.Create))
            var encoder = new PngBitmapEncoder();