diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index d867008d7..b6ef4be21 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -82,8 +82,15 @@ namespace SixLabors.ImageSharp.Drawing.Processors int maxIntersections = region.MaxIntersections; float subpixelCount = 4; + + // we need to offset the pixel grid to account for when we outline a path. + // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] + // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# + // region to alline with the pixel grid. + float offset = 0.5f; if (this.Options.Antialias) { + offset = 0f; // we are antialising skip offsetting as real antalising should take care of offset. subpixelCount = this.Options.AntialiasSubpixelDepth; if (subpixelCount < 4) { @@ -117,7 +124,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors float subpixelFractionPoint = subpixelFraction / subpixelCount; for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction) { - int pointsFound = region.Scan(subPixel, buffer, 0); + int pointsFound = region.Scan(subPixel + offset, buffer, 0); if (pointsFound == 0) { // nothing on this line skip @@ -131,8 +138,8 @@ namespace SixLabors.ImageSharp.Drawing.Processors // points will be paired up float scanStart = buffer[point] - minX; float scanEnd = buffer[point + 1] - minX; - int startX = (int)MathF.Floor(scanStart); - int endX = (int)MathF.Floor(scanEnd); + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); if (startX >= 0 && startX < scanline.Length) { @@ -169,7 +176,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors { for (int x = 0; x < scanlineWidth; x++) { - if (scanline[x] > 0.5) + if (scanline[x] >= 0.5) { scanline[x] = 1; } diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs index 5d2ef1436..625f95b63 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs @@ -975,7 +975,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif [ExifTagDescription((ushort)71, "Fired, Red-eye reduction, Return detected")] [ExifTagDescription((ushort)73, "On, Red-eye reduction")] [ExifTagDescription((ushort)77, "On, Red-eye reduction, Return not detected")] - [ExifTagDescription((ushort)69, "On, Red-eye reduction, Return detected")] + [ExifTagDescription((ushort)79, "On, Red-eye reduction, Return detected")] [ExifTagDescription((ushort)80, "Off, Red-eye reduction")] [ExifTagDescription((ushort)88, "Auto, Did not fire, Red-eye reduction")] [ExifTagDescription((ushort)89, "Auto, Fired, Red-eye reduction")] diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs index c210b66ed..be7c8adb0 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs @@ -81,13 +81,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); + Assert.True(Rgba32.HotPink == sourcePixels[11, 11], "[11, 11] wrong"); - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 150]); + Assert.True(Rgba32.HotPink == sourcePixels[199, 149], "[199, 149] wrong"); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); + Assert.True(Rgba32.HotPink == sourcePixels[50, 50], "[50, 50] wrong"); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); + Assert.True(Rgba32.Blue == sourcePixels[2, 2], "[2, 2] wrong"); } } } diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs new file mode 100644 index 000000000..b77112ba6 --- /dev/null +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using SixLabors.Primitives; +using SixLabors.ImageSharp.Advanced; +using Xunit; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests.Issues +{ + public class Issue412 + { + [Theory] + [WithBlankImages(40, 30, PixelTypes.Rgba32)] + public void AllPixelsExpectedToBeRedWhenAntialisedDisabled(TestImageProvider provider) where TPixel : struct, IPixel + { + using (var image = provider.GetImage()) + { + image.Mutate( + context => + { + for (var i = 0; i < 40; ++i) + { + context.DrawLines( + NamedColors.Black, + 1, + new[] + { + new PointF(i, 0.1066f), + new PointF(i, 10.1066f) + }, + new GraphicsOptions(true)); + + context.DrawLines( + NamedColors.Red, + 1, + new[] + { + new PointF(i, 15.1066f), + new PointF(i, 25.1066f) + }, + new GraphicsOptions(false)); + } + }); + + image.DebugSave(provider); + for (var y = 15; y < 25; y++) + { + for (var x = 0; x < 40; x++) + { + + Assert.True(NamedColors.Red.Equals(image[x, y]), $"expected {NamedColors.Red} but found {image[x, y]} at [{x}, {y}]"); + } + } + } + } + } +}