Closed atruskie closed 3 years ago
We are likely dealing with some fallout from #96. (Not unexpected considering the volume of the change.) Need to look into this.
I just realized the Antialiasing = false
part of this issue is misleading. The bug occurs either with ( Antialiasing = true
) or without (Antialiasing = false
) antialiasing.
@antonfirsov I can get all the tests to pass including the new ones listed here by adding && i0 < this.edges.Length
to the while loop, however I have no idea whether this is a valid fix. (I'm really not confident.)
private void SkipEdgesBeforeMinY()
{
if (this.edges.Length == 0)
{
return;
}
this.SubPixelY = this.edges[this.sorted0[0]].Y0;
int i0 = 1;
int i1 = 0;
// Do fake scans for the lines belonging to edge start and endpoints before minY
while (this.SubPixelY < this.minY && i0 < this.edges.Length)
{
this.EnterEdges();
this.LeaveEdges();
this.activeEdges.RemoveLeavingEdges();
float y0 = this.edges[this.sorted0[i0]].Y0;
float y1 = this.edges[this.sorted1[i1]].Y1;
if (y0 < y1)
{
this.SubPixelY = y0;
i0++;
}
else
{
this.SubPixelY = y1;
i1++;
}
}
}
Just to mention. Also happens to me. I have AntiAlias= true and this happens if I draw an ellipsis with one part outside of the image (eg. R=3 and X,Y =0,3) or drawing lines (0,0)-(0,30) with line thickness = 2 for example.
Just for your information, the issue can be reproduced even if the thickness of the line is 1. I got an ImageProcessingException
when running this piece of code on Windows 10 v1903:
static void Main()
{
Image<Rgba32> image = new Image<Rgba32>(width: 500, height: 400);
var startPoint = new PointF(493.55447f, -87.83895f);
var endPoint = new PointF(500.0656f, 174.81201f);
image.Mutate(x => x.DrawLines(Color.Black, thickness: 1, startPoint, endPoint));
}
The minimal Visual Studio solution to reproduce the issue: DrawLinesIssue.zip
This method was developed in rush, after realizing that I need to handle the cases where lines are outside the drawing bounds ... looks like testing was insufficient.
I need more time to debug into that crazy code and understand exactly why is the overflow happening. We should not block on this, so @JimBobSquarePants feel free to raise a PR with your fix, since it seems to make things better. Just let's include tests from both the OP and https://github.com/SixLabors/ImageSharp.Drawing/issues/108#issuecomment-755988422, and also have a look at the outputs.
@antonfirsov Looks like my fix is bad. It's offsetting the values not actually processing the virtual edges.
What I'm seeing during debugging given a stroke width of 3.
while (this.SubPixelY < this.minY)
{
this.EnterEdges();
this.LeaveEdges();
this.activeEdges.RemoveLeavingEdges();
float y0 = this.edges[this.sorted0[i0]].Y0; // Always -1
float y1 = this.edges[this.sorted1[i1]].Y1; // Always 2
// Always true
if (y0 < y1)
{
this.SubPixelY = y0;
i0++;
}
else
{
this.SubPixelY = y1;
i1++;
}
}
Looks like I have a fix. Will do some final testing
Prerequisites
DEBUG
andRELEASE
modeDescription
Drawing a horizontal line across the top edge of an image results in an exception if the stroke width is greater than
1.5f
and antialiasing is disabled.Steps to Reproduce
The following test code was run and adapted from
https://github.com/SixLabors/ImageSharp.Drawing/blob/48a803e51df044f33e061fc140e81aec5b3aa310/tests/ImageSharp.Drawing.Tests/Issues/Issue_28.cs#L18-L35
Then:
C:\Work\Github\ImageSharp.Drawing\tests\ImageSharp.Drawing.Tests> dotnet test -c Release --filter "Issue_28"
The existing tests pass, the altered stroke width tests fail:
System Configuration
Seems to be related to the new PolygonScanner SkipEdgesBeforeMinY code.