I'm currently in the process of migrating a project that uses System.Drawing.Bitmap
over to use ImageSharp. As part of this migration, I am migrating logic that would draw circles onto the bitmap using the Graphics.FromImage
function.
The problem I am faced with is, if the circle previously went outside the bounds of the Bitmap, this was previously fine and it would draw the parts of the circle it could, simply clipping the drawn circle. With ImageSharp, this would, understandably throw an out of bounds exception.
A simplified implementation:
void Main()
{
var width = 70;
var height = 70;
SystemDrawingImpl(width, height);
ImageSharpImpl(width, height);
}
private void SystemDrawingImpl(int width, int height)
{
using var bitmap = new Bitmap(64, 64);
using var graphics = Graphics.FromImage(bitmap);
var xLocation = ((bitmap.Width / 2) - (width / 2)) - 1;
var yLocation = ((bitmap.Height / 2) - (height / 2)) - 1;
graphics.DrawEllipse(new System.Drawing.Pen(System.Drawing.Color.Green, 1.1f), xLocation, yLocation, width, height);
var memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Jpeg);
Util.Image(memoryStream.ToArray()).Dump();
}
private void ImageSharpImpl(int width, int height)
{
using var image = new Image<Rgba32>(64, 64);
var brush = SixLabors.ImageSharp.Drawing.Processing.Brushes.Solid(SixLabors.ImageSharp.Color.Green);
var pen = SixLabors.ImageSharp.Drawing.Processing.Pens.Solid(SixLabors.ImageSharp.Color.Green, 0.1f);
var ellipse = new EllipsePolygon(32, 32, width, height);
image.Mutate(ctx => ctx.Draw(pen, ellipse));
var memoryStream = new MemoryStream();
image.Save(memoryStream, new JpegEncoder());
Util.Image(memoryStream.ToArray()).Dump();
}
For which the output for System.Drawing would be:
The output/exception from ImageSharp is:
ImageProcessingException: An error occurred when processing the image using FillRegionProcessor`1. See the inner exception for more detail.
ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'edgeIdx')
I was wondering if there was a way to get a similar output. Is there a way in which I'd be able to still draw the parts of the ellipse that is possible?
I have attempted to remove the points that are "invalid" via a simple where:
var points = ellipse.Points.ToArray();
var validPoints = points.Where(x => (x.X <= image.Width && x.X >= 0) && (x.Y <= image.Height && x.Y >= 0)).ToArray();
image.Mutate(ctx => ctx.DrawPolygon(pen, validPoints));
However this will still try to create a fully joined path which is not the desired effect:
Any advice on how I might achieve this would be appreciated