Reputation: 1460
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?
Upvotes: 1
Views: 2933
Reputation: 445
Since the accepted answer was throwing a deprecated warning for me I rewrote the code like this.
public Bitmap? CreateBitmap(StreamGeometry streamGeometry, Brush brush)
{
var testImage = new DrawingImage
{
Drawing = new GeometryDrawing
{
Geometry = streamGeometry,
Brush = brush
}
};
var pixelSize = new PixelSize((int)testImage.Size.Width, (int)testImage.Size.Height);
Bitmap? returnImage = null;
using (MemoryStream memoryStream = new())
{
using (RenderTargetBitmap bitmap = new(pixelSize, new Vector(72, 72)))
{
using (DrawingContext ctx = new(bitmap.CreateDrawingContext(null)))
{
testImage.Drawing.Draw(ctx);
}
bitmap.Save(memoryStream);
}
memoryStream.Seek(0, SeekOrigin.Begin);
returnImage = new Bitmap(memoryStream);
}
return returnImage;
}
It is working for Avalonia 0.10.18 maybe it will break with the 11.0.0 release.
Hopefully this will help someone.
It did break with 11.0.0 so here is an updated version. The DrawingContext creation did get simplified.
public Bitmap? CreateBitmap(StreamGeometry streamGeometry, Brush brush)
{
var internalImage = new DrawingImage
{
Drawing = new GeometryDrawing
{
Geometry = streamGeometry,
Brush = brush
}
};
var pixelSize = new PixelSize((int)internalImage.Size.Width, (int)internalImage.Size.Height);
Bitmap? returnImage = null;
using (MemoryStream memoryStream = new())
{
using (RenderTargetBitmap bitmap = new(pixelSize, new Vector(72, 72)))
{
using (DrawingContext ctx = bitmap.CreateDrawingContext())
{
internalImage.Drawing.Draw(ctx);
}
bitmap.Save(memoryStream);
}
memoryStream.Seek(0, SeekOrigin.Begin);
returnImage = new Bitmap(memoryStream);
}
return returnImage;
}
Upvotes: 1
Reputation: 3623
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);
}
}
Upvotes: 2