Search code examples
c#imagingavaloniaui

Drawing a geometry onto a Bitmap (Avalonia)


My question is pretty straight forward: Is it possible to draw a Avalonia.Media.Geometry onto a Avalonia.Media.Bitmap so that I can save the resulting Image to a Steam as well as use the whole thing with an ImageBrush?

In the System.Drawing namespace one could simply call Graphics.FromImage(mySystemDrawingBitmap); to get a Graphics object which can then be used to draw whatever geometry you want.

Is there a similar easy approach to this in Avalonia? I dug up something called RenderTargetBitmap from the documentation which looks promising as it has a method called CreateDrawingContext but it apparently needs an IVisualBrushRenderer (whatever that may be) instance as a parameter to work. There seems to be a thing called ImmediateRenderer that implements said interface however it requires an Avalonia.VisualTree.IVisual itself as a parameter in it's constructor and at this stage I'm kinda doubting the usefulness of the RenderTargetBitmap for my problem as it seems to have a massive overhead of randomly required object instances I don't really want or need and I'm not going to create a dummy IVisual instance just to draw something on a bitmap. This just has a horrible code smell to it.

Sooo: Rendering a Avalonia.Media.Geometry (created with Geometry.Parse() for example) onto a Avalonia.Media.Bitmap. How are you actually supposed to do it?


Solution

  • void RenderToFile(Geometry geometry, Brush brush, string path)
    {
        var control = new DrawingPresenter()
        {
            Drawing = new GeometryDrawing
            {
                Geometry = geometry, Brush = brush,
            },
            Width = geometry.Bounds.Right,
            Height = geometry.Bounds.Bottom
        };
    
        RenderToFile(control, path);
    }
    
    void RenderToFile(Control target, string path)
    {
        var pixelSize = new PixelSize((int) target.Width, (int) target.Height);
        var size = new Size(target.Width, target.Height);
        using (RenderTargetBitmap bitmap = new RenderTargetBitmap(pixelSize, new Vector(96, 96)))
        {
            target.Measure(size);
            target.Arrange(new Rect(size));
            bitmap.Render(target);
            bitmap.Save(path);
        }
    }