From 6741c280e3017cdb28199e4a00f977cc8540c06d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 15:49:58 +0200 Subject: [PATCH 01/27] temporarily disable target frameworks --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 ++- src/ImageSharp/ImageSharp.csproj | 3 ++- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 915915f6cc..fdeb27a770 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0 + + netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index d734648f41..4abe2f57a2 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0;net472 + + netstandard2.0 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 0b727f30ce..efdf89964c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,7 @@  - netcoreapp2.1;net462;net472 + + netcoreapp2.1 True latest full From 7e8357c5392ccff9f7d5b64e15dd61d035e3fac6 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 17:00:16 +0200 Subject: [PATCH 02/27] validating tests for: DrawPath, FillComplexPolygon --- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 133 +++++++----------- .../Drawing/FillComplexPolygonTests.cs | 62 ++++++++ ...tternTests.cs => FillPatternBrushTests.cs} | 6 +- .../Drawing/SolidComplexPolygonTests.cs | 109 -------------- .../Processors/Overlays/OverlayTestBase.cs | 3 +- .../TestUtilities/TestUtils.cs | 9 +- tests/Images/External | 2 +- 7 files changed, 125 insertions(+), 199 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs rename tests/ImageSharp.Tests/Drawing/{FillPatternTests.cs => FillPatternBrushTests.cs} (98%) delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index d2485f334a..c638107b81 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -1,112 +1,79 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.Primitives; using SixLabors.Shapes; using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class DrawPathTests : FileTestBase + [GroupOutput("Drawing")] + public class DrawPathTests { - [Fact] - public void ImageShouldBeOverlayedByPath() + public static readonly TheoryData DrawPathData = new TheoryData + { + { "White", 255, 1.5f }, + { "Red", 255, 3 }, + { "HotPink", 255, 5 }, + { "HotPink", 150, 5 }, + { "White", 255, 15 }, + }; + + [Theory] + [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] + public void DrawPath(TestImageProvider provider, string colorName, byte alpha, float thickness) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - using (var image = new Image(500, 500)) - { - var linerSegemnt = new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300)); - var bazierSegment = new CubicBezierLineSegment( - new Vector2(50, 300), - new Vector2(500, 500), - new Vector2(60, 10), - new Vector2(10, 400)); - - var p = new Path(linerSegemnt, bazierSegment); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, p)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedPathWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - var linerSegemnt = new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - ); - - var bazierSegment = new CubicBezierLineSegment(new Vector2(50, 300), + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300)); + var bazierSegment = new CubicBezierLineSegment( + new Vector2(50, 300), new Vector2(500, 500), new Vector2(60, 10), new Vector2(10, 400)); - var p = new Path(linerSegemnt, bazierSegment); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(color, 10, p)); - image.Save($"{path}/Opacity.png"); + var path = new Path(linerSegemnt, bazierSegment); - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); + Rgba32 rgba = TestUtils.GetColorByName(colorName); + rgba.A = alpha; + Color color = rgba; - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[11, 11]); + FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } + provider.RunValidatingProcessorTest( + x => x.Draw(color.ToPixel(), thickness, path), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } - [Fact] - public void PathExtendingOffEdgeOfImageShouldNotBeCropped() + [Theory] + [WithSolidFilledImages(256, 256, "Black", PixelTypes.Rgba32)] + public void PathExtendingOffEdgeOfImageShouldNotBeCropped(TestImageProvider provider) + where TPixel : struct, IPixel { - - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - using (var image = new Image(256, 256)) - { - image.Mutate(x => x.Fill(Rgba32.Black)); - Pen pen = Pens.Solid(Rgba32.White, 5f); - - for (int i = 0; i < 300; i += 20) - { - image.Mutate( - x => x.DrawLines( - pen, - new SixLabors.Primitives.PointF[] { new Vector2(100, 2), new Vector2(-10, i) })); - } - - image.Save($"{path}/ClippedLines.png"); - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.White, sourcePixels[0, 90]); - } + Color color = Color.White; + Pen pen = Pens.Solid(color.ToPixel(), 5f); + + provider.RunValidatingProcessorTest( + x => + { + for (int i = 0; i < 300; i += 20) + { + PointF[] points = new PointF[] { new Vector2(100, 2), new Vector2(-10, i) }; + x.DrawLines(pen, points); + } + }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs new file mode 100644 index 0000000000..3887cb9a7a --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs @@ -0,0 +1,62 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class FillComplexPolygonTests + { + [Theory] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, false)] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, true, false)] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, true)] + public void ComplexPolygon_SolidFill(TestImageProvider provider, bool overlap, bool transparent) + where TPixel :struct, IPixel + { + var simplePath = new Polygon(new LinearLineSegment( + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300))); + + var hole1 = new Polygon(new LinearLineSegment( + new Vector2(37, 85), + overlap ? new Vector2(130, 40) : new Vector2(93, 85), + new Vector2(65, 137))); + IPath clipped = simplePath.Clip(hole1); + + Rgba32 colorRgba = Rgba32.HotPink; + if (transparent) + { + colorRgba.A = 150; + } + + Color color = colorRgba; + + string testDetails = ""; + if (overlap) + { + testDetails += "_Overlap"; + } + + if (transparent) + { + testDetails += "_Transparent"; + } + + provider.RunValidatingProcessorTest( + x => x.Fill(color.ToPixel(), clipped), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs similarity index 98% rename from tests/ImageSharp.Tests/Drawing/FillPatternTests.cs rename to tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs index b310c7afc6..dcc689fe1c 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs @@ -12,11 +12,11 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class FillPatternBrushTests : FileTestBase + public class FillPatternBrushTests { private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) { - string path = TestEnvironment.CreateOutputDirectory("Fill", "PatternBrush"); + string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); using (var image = new Image(20, 20)) { image.Mutate(x => x.Fill(background).Fill(brush)); @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } - image.Mutate(x => x.Resize(80, 80)); + image.Mutate(x => x.Resize(80, 80, KnownResamplers.NearestNeighbor)); image.Save($"{path}/{name}x4.png"); } } diff --git a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs deleted file mode 100644 index 0e997ad7eb..0000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class SolidComplexPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - IPath clipped = simplePath.Clip(hole1); - // var clipped = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20)); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, clipped)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOverlap() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(130, 40), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleOverlapping.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(color, simplePath.Clip(hole1))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs index 788f7e1ade..eaad82f9a3 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs @@ -27,8 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays where TPixel : struct, IPixel { provider.Utility.TestGroupName = this.GetType().Name; - var f = (FieldInfo)typeof(Color).GetMember(colorName)[0]; - Color color = (Color)f.GetValue(null); + Color color = TestUtils.GetColorByName(colorName); provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index e51aa28d8f..5db0c08282 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -141,8 +141,15 @@ namespace SixLabors.ImageSharp.Tests /// The pixel types internal static PixelTypes[] GetAllPixelTypes() => (PixelTypes[])Enum.GetValues(typeof(PixelTypes)); + internal static Color GetColorByName(string colorName) + { + var f = (FieldInfo)typeof(Color).GetMember(colorName)[0]; + return (Color)f.GetValue(null); + } + internal static TPixel GetPixelOfNamedColor(string colorName) - where TPixel : struct, IPixel => (TPixel)typeof(NamedColors).GetTypeInfo().GetField(colorName).GetValue(null); + where TPixel : struct, IPixel => + GetColorByName(colorName).ToPixel(); /// /// Utility for testing image processor extension methods: diff --git a/tests/Images/External b/tests/Images/External index c057090b44..d83843deed 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc +Subproject commit d83843deedc43712f29f631aab090640b4f54946 From cf8005deb2ba98063af51414009f7e4aca2edc32 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 23:53:27 +0200 Subject: [PATCH 03/27] validation in DrawImageTest --- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 198 ------------------ .../Drawing/DrawImageTests.cs | 174 +++++++++++++++ .../TestUtilities/TestImageExtensions.cs | 25 ++- tests/Images/External | 2 +- 4 files changed, 192 insertions(+), 207 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawImageTest.cs create mode 100644 tests/ImageSharp.Tests/Drawing/DrawImageTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs deleted file mode 100644 index 54b04390ec..0000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - [GroupOutput("Drawing")] - public class DrawImageTest : FileTestBase - { - private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; - - public static readonly string[] TestFiles = { - TestImages.Jpeg.Baseline.Calliphora, - TestImages.Bmp.Car, - TestImages.Png.Splash, - TestImages.Gif.Rings - }; - - [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Add)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Screen)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Darken)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.HardLight)] - public void ImageShouldApplyDrawImage(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) - { - blend.Mutate(x => x.Resize(image.Width / 2, image.Height / 2)); - image.Mutate(x => x.DrawImage(blend, new Point(image.Width / 4, image.Height / 4), mode, .75f)); - image.DebugSave(provider, new { mode }); - } - } - - [Theory] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Normal)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Add)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Screen)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Darken)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.HardLight)] - public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image background = provider.GetImage()) - using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes)) - { - background.Mutate(x => x.DrawImage(source, mode, 1F)); - VerifyImage(provider, mode, background); - } - } - - [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - public void ImageShouldDrawTransformedImage(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) - { - AffineTransformBuilder builder = new AffineTransformBuilder() - .AppendRotationDegrees(45F) - .AppendScale(new SizeF(.25F, .25F)) - .AppendTranslation(new PointF(10, 10)); - - // Apply a background color so we can see the translation. - blend.Mutate(x => x.Transform(builder)); - blend.Mutate(x => x.BackgroundColor(Color.HotPink)); - - // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor - var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); - image.Mutate(x => x.DrawImage(blend, position, mode, .75F)); - image.DebugSave(provider, new[] { "Transformed" }); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandleNegativeLocation(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = -25; - Rgba32 backgroundPixel = background[0, 0]; - Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[0, 0]); - - background.DebugSave(provider, testOutputDetails: "Negative"); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocation(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 25; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); - - background.DebugSave(provider, testOutputDetails: "Positive"); - } - } - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocationTruncatedOverlay(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 75; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); - - background.DebugSave(provider, testOutputDetails: "PositiveTruncated"); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)] - public void NonOverlappingImageThrows(TestImageProvider provider, int x, int y) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(Configuration.Default, 10, 10, Rgba32.Black)) - { - ImageProcessingException ex = Assert.Throws(Test); - - Assert.Contains("does not overlap", ex.ToString()); - - void Test() - { - background.Mutate(context => context.DrawImage(overlay, new Point(x, y), GraphicsOptions.Default)); - } - } - } - - private static void VerifyImage( - TestImageProvider provider, - PixelColorBlendingMode mode, - Image img) - where TPixel : struct, IPixel - { - img.DebugSave( - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - var comparer = ImageComparer.TolerantPercentage(0.01F, 3); - img.CompareFirstFrameToReferenceOutput(comparer, - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs new file mode 100644 index 0000000000..f4e9b7b450 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -0,0 +1,174 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawImageTests + { + public static readonly TheoryData BlendingModes = new TheoryData + { + PixelColorBlendingMode.Normal, + PixelColorBlendingMode.Multiply, + PixelColorBlendingMode.Add, + PixelColorBlendingMode.Subtract, + PixelColorBlendingMode.Screen, + PixelColorBlendingMode.Darken, + PixelColorBlendingMode.Lighten, + PixelColorBlendingMode.Overlay, + PixelColorBlendingMode.HardLight, + }; + + [Theory] + [WithFile( TestImages.Png.Rainbow,nameof(BlendingModes), PixelTypes.Rgba32)] + public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode) + where TPixel : struct, IPixel + { + using (Image background = provider.GetImage()) + using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes)) + { + background.Mutate(x => x.DrawImage(source, mode, 1F)); + background.DebugSave( + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + var comparer = ImageComparer.TolerantPercentage(0.01F); + background.CompareToReferenceOutput(comparer, + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgr24, TestImages.Png.Bike, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.75f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Multiply, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Add, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Subtract, 0.5f)] + + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + public void WorksWithDifferentConfigurations( + TestImageProvider provider, + string brushImage, + PixelColorBlendingMode mode, + float opacity) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + using (var blend = Image.Load(TestFile.Create(brushImage).Bytes)) + { + Size size = new Size(image.Width * 3 / 4, image.Height *3/ 4); + Point position = new Point(image.Width / 8, image.Height / 8); + blend.Mutate(x => x.Resize(size.Width, size.Height, KnownResamplers.Bicubic)); + image.Mutate(x => x.DrawImage(blend, position, mode, opacity)); + FormattableString testInfo = $"{System.IO.Path.GetFileNameWithoutExtension(brushImage)}-{mode}-{opacity}"; + + PngEncoder encoder = new PngEncoder(); + + if (provider.PixelType == PixelTypes.Rgba64) + { + encoder.BitDepth = PngBitDepth.Bit16; + } + + image.DebugSave(provider, testInfo, encoder: encoder); + image.CompareToReferenceOutput(provider, testInfo); + } + } + + + [Theory] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 0, 0)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 25)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 75, 50)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, -25, -30)] + public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(50, 50)) + { + overlay.Mutate(c => c.Fill(Rgba32.Black)); + + background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); + + background.DebugSave( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + background.CompareToReferenceOutput( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] + public void DrawTransformed(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) + { + AffineTransformBuilder builder = new AffineTransformBuilder() + .AppendRotationDegrees(45F) + .AppendScale(new SizeF(.25F, .25F)) + .AppendTranslation(new PointF(10, 10)); + + // Apply a background color so we can see the translation. + blend.Mutate(x => x.Transform(builder)); + blend.Mutate(x => x.BackgroundColor(Color.HotPink)); + + // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor + var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); + image.Mutate(x => x.DrawImage(blend, position, .75F)); + + image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + } + } + + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)] + public void NonOverlappingImageThrows(TestImageProvider provider, int x, int y) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(Configuration.Default, 10, 10, Rgba32.Black)) + { + ImageProcessingException ex = Assert.Throws(Test); + + Assert.Contains("does not overlap", ex.ToString()); + + void Test() + { + background.Mutate(context => context.DrawImage(overlay, new Point(x, y), GraphicsOptions.Default)); + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 6ca3ed6f9f..c5aa1fb944 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -61,7 +61,8 @@ namespace SixLabors.ImageSharp.Tests FormattableString testOutputDetails, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageEncoder encoder = null) where TPixel : struct, IPixel { return image.DebugSave( @@ -69,7 +70,8 @@ namespace SixLabors.ImageSharp.Tests (object)testOutputDetails, extension, appendPixelTypeToFileName, - appendSourceFileOrDescription); + appendSourceFileOrDescription, + encoder); } /// @@ -82,13 +84,15 @@ namespace SixLabors.ImageSharp.Tests /// The extension /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. + /// Custom encoder to use. public static Image DebugSave( this Image image, ITestImageProvider provider, object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageEncoder encoder = null) where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) @@ -102,7 +106,8 @@ namespace SixLabors.ImageSharp.Tests extension, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName, - appendSourceFileOrDescription: appendSourceFileOrDescription); + appendSourceFileOrDescription: appendSourceFileOrDescription, + encoder: encoder); return image; } @@ -255,6 +260,7 @@ namespace SixLabors.ImageSharp.Tests /// A boolean indicating whether we should debug save + compare against a grayscale image, smaller in size. /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. + /// A custom decoder. /// public static Image CompareToReferenceOutput( this Image image, @@ -264,7 +270,8 @@ namespace SixLabors.ImageSharp.Tests string extension = "png", bool grayscale = false, bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageDecoder decoder = null) where TPixel : struct, IPixel { using (Image referenceImage = GetReferenceOutputImage( @@ -272,7 +279,8 @@ namespace SixLabors.ImageSharp.Tests testOutputDetails, extension, appendPixelTypeToFileName, - appendSourceFileOrDescription)) + appendSourceFileOrDescription, + decoder)) { comparer.VerifySimilarity(referenceImage, image); } @@ -356,7 +364,8 @@ namespace SixLabors.ImageSharp.Tests object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageDecoder decoder = null) where TPixel : struct, IPixel { string referenceOutputFile = provider.Utility.GetReferenceOutputFileName( @@ -370,7 +379,7 @@ namespace SixLabors.ImageSharp.Tests throw new System.IO.FileNotFoundException("Reference output file missing: " + referenceOutputFile, referenceOutputFile); } - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(referenceOutputFile); + decoder = decoder ?? TestEnvironment.GetReferenceDecoder(referenceOutputFile); return Image.Load(referenceOutputFile, decoder); } diff --git a/tests/Images/External b/tests/Images/External index d83843deed..dc5afda9a4 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit d83843deedc43712f29f631aab090640b4f54946 +Subproject commit dc5afda9a4ad69dc3526d49ceb1d27610064f2af From 5ab0ad2dffb202dd802b88c89b3c44af3c8ac1a8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 00:52:35 +0200 Subject: [PATCH 04/27] RecolorImageTests --- .../{BeziersTests.cs => DrawBezierTests.cs} | 10 ++-- .../Drawing/RecolorImageTest.cs | 48 ----------------- .../Drawing/RecolorImageTests.cs | 51 +++++++++++++++++++ tests/Images/External | 2 +- 4 files changed, 57 insertions(+), 54 deletions(-) rename tests/ImageSharp.Tests/Drawing/{BeziersTests.cs => DrawBezierTests.cs} (93%) delete mode 100644 tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs create mode 100644 tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs similarity index 93% rename from tests/ImageSharp.Tests/Drawing/BeziersTests.cs rename to tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index cc8f27f3a2..d82221ca67 100644 --- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -11,13 +11,13 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class Beziers : FileTestBase + public class DrawBezierTests { [Fact] public void ImageShouldBeOverlayedByBezierLine() { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); - using (var image = new Image(500, 500)) + string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); + using (var image = new Image(350, 450)) { image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( @@ -51,11 +51,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing [Fact] public void ImageShouldBeOverlayedBezierLineWithOpacity() { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); + string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - using (var image = new Image(500, 500)) + using (var image = new Image(350, 450)) { image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs deleted file mode 100644 index b064d9c964..0000000000 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class RecolorImageTest : FileTestBase - { - [Fact] - public void ImageShouldRecolorYellowToHotPink() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "RecolorImage"); - - var brush = new RecolorBrush(Rgba32.Yellow, Rgba32.HotPink, 0.2f); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateRgba32Image()) - { - image.Mutate(x => x.Fill(brush)); - image.Save($"{path}/{file.FileName}"); - } - } - } - - [Fact] - public void ImageShouldRecolorYellowToHotPinkInARectangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "RecolorImage"); - - var brush = new RecolorBrush(Rgba32.Yellow, Rgba32.HotPink, 0.2f); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateRgba32Image()) - { - int imageHeight = image.Height; - image.Mutate(x => x.Fill(brush, new Rectangle(0, imageHeight / 2 - imageHeight / 4, image.Width, imageHeight / 2))); - image.Save($"{path}/Shaped_{file.FileName}"); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs new file mode 100644 index 0000000000..cb671a53d4 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Primitives; +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + [GroupOutput("Drawing")] + public class RecolorImageTests + { + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, "Yellow", "Pink", 0.2f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.6f)] + public void Recolor(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) + where TPixel : struct, IPixel + { + Color sourceColor = TestUtils.GetColorByName(sourceColorName); + Color targetColor = TestUtils.GetColorByName(targetColorName); + var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + + FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; + provider.RunValidatingProcessorTest(x => x.Fill(brush), testInfo); + } + + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] + public void Recolor_InBox(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) + where TPixel : struct, IPixel + { + Color sourceColor = TestUtils.GetColorByName(sourceColorName); + Color targetColor = TestUtils.GetColorByName(targetColorName); + var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + + FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; + provider.RunValidatingProcessorTest(x => + { + Size size = x.GetCurrentSize(); + var rectangle = new Rectangle(0, size.Height / 2 - size.Height / 4, size.Width, size.Height / 2); + x.Fill(brush, rectangle); + }, testInfo); + } + } +} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index dc5afda9a4..5036d47ec2 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit dc5afda9a4ad69dc3526d49ceb1d27610064f2af +Subproject commit 5036d47ec2393d90efb6f3864d828e2e4381947f From 52fbbda7e1c624ade12a3c3e7131848248b579a8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 02:34:48 +0200 Subject: [PATCH 05/27] FillPolygonTests --- src/ImageSharp/Color/Color.Conversions.cs | 14 + src/ImageSharp/Color/Color.cs | 12 + tests/ImageSharp.Tests/Color/ColorTests.cs | 11 + .../Drawing/FillPolygonTests.cs | 155 +++++++++++ .../Drawing/RecolorImageTests.cs | 3 +- .../Drawing/SolidPolygonTests.cs | 240 ------------------ tests/Images/External | 2 +- 7 files changed, 195 insertions(+), 242 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 001aee5a4f..20dca67706 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -117,6 +117,13 @@ namespace SixLabors.ImageSharp /// The . public static implicit operator Color(Bgr24 source) => new Color(source); + /// + /// Converts an to . + /// + /// The . + /// The . + public static explicit operator Color(Vector4 source) => new Color(source); + /// /// Converts a to . /// @@ -158,5 +165,12 @@ namespace SixLabors.ImageSharp /// The . /// The . public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static explicit operator Vector4(Color color) => color.data.ToVector4(); } } \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index f2f8578d83..fe35033147 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -94,6 +94,18 @@ namespace SixLabors.ImageSharp return new Color(rgba); } + /// + /// Alters the alpha channel of the color, returning a new instance. + /// + /// The new value of alpha [0..1]. + /// The color having it's alpha channel altered. + public Color WithAlpha(float alpha) + { + Vector4 v = (Vector4)this; + v.W = alpha; + return new Color(v); + } + /// /// Gets the hexadecimal representation of the color instance in rrggbbaa form. /// diff --git a/tests/ImageSharp.Tests/Color/ColorTests.cs b/tests/ImageSharp.Tests/Color/ColorTests.cs index 729ef94e3c..e9e22ccdd9 100644 --- a/tests/ImageSharp.Tests/Color/ColorTests.cs +++ b/tests/ImageSharp.Tests/Color/ColorTests.cs @@ -13,6 +13,17 @@ namespace SixLabors.ImageSharp.Tests { public partial class ColorTests { + [Fact] + public void WithAlpha() + { + Color c1 = Color.FromRgba(111, 222, 55, 255); + Color c2 = c1.WithAlpha(0.5f); + + Rgba32 expected = new Rgba32(111, 222, 55, 128); + + Assert.Equal(expected, (Rgba32)c2); + } + [Fact] public void Equality_WhenTrue() { diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs new file mode 100644 index 0000000000..43029e6957 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -0,0 +1,155 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class FillPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, true)] + public void FillPolygon_Solid(TestImageProvider provider, string colorName, float alpha, bool antialias) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A{alpha}{aa}"; + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(options, color.ToPixel(), simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] + public void FillPolygon_Concave(TestImageProvider provider) + where TPixel : struct, IPixel + { + var points = new SixLabors.Primitives.PointF[] + { + new Vector2(8, 8), + new Vector2(64, 8), + new Vector2(64, 64), + new Vector2(120, 64), + new Vector2(120, 120), + new Vector2(8, 120) + }; + + Color color = Color.LightGreen; + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(color.ToPixel(), points), + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32)] + public void FillPolygon_Pattern(TestImageProvider provider) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = Color.Yellow; + + var brush = Brushes.Horizontal(color.ToPixel()); + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(brush, simplePath), + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Png.Ducky)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Bmp.Car)] + public void FillPolygon_ImageBrush(TestImageProvider provider, string brushImageName) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 50), new Vector2(50, 200) + }; + + using (Image brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) + { + var brush = new ImageBrush(brushImage); + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(brush, simplePath), + System.IO.Path.GetFileNameWithoutExtension(brushImageName), + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithBasicTestPatternImages(250, 250, PixelTypes.Rgba32)] + public void Fill_RectangularPolygon(TestImageProvider provider) + where TPixel : struct, IPixel + { + var polygon = new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140); + Color color = Color.White; + + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 50, 0f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, 20f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, -180f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 5, 70, 0f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 7, 80, -180f)] + public void Fill_RegularPolygon(TestImageProvider provider, int vertices, float radius, float angleDeg) + where TPixel : struct, IPixel + { + float angle = GeometryUtilities.DegreeToRadian(angleDeg); + var polygon = new RegularPolygon(100, 100, vertices, radius, angle); + Color color = Color.Yellow; + + FormattableString testOutput = $"V({vertices})_R({radius})_Ang({angleDeg})"; + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + testOutput, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] + public void Fill_EllipsePolygon(TestImageProvider provider) + where TPixel : struct, IPixel + { + var polygon = new EllipsePolygon(100, 100, 80, 120); + Color color = Color.Azure; + + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs index cb671a53d4..461ca700f7 100644 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -6,9 +6,10 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; + using Xunit; -namespace SixLabors.ImageSharp.Tests +namespace SixLabors.ImageSharp.Tests.Drawing { [GroupOutput("Drawing")] public class RecolorImageTests diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs deleted file mode 100644 index 6a299aad7b..0000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class SolidPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByFilledPolygon() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - SixLabors.Primitives.PointF[] simplePath = { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.FillPolygon(new GraphicsOptions(true), Rgba32.HotPink, simplePath)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonWithPattern() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate( - x => x.FillPolygon(new GraphicsOptions(true), Brushes.Horizontal(Rgba32.HotPink), simplePath)); - image.Save($"{path}/Pattern.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonNoAntialias() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.FillPolygon( - new GraphicsOptions(false), - Rgba32.HotPink, - simplePath)); - image.Save($"{path}/Simple_NoAntialias.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.True(Rgba32.HotPink == sourcePixels[11, 11], "[11, 11] wrong"); - - Assert.True(Rgba32.HotPink == sourcePixels[199, 149], "[199, 149] wrong"); - - Assert.True(Rgba32.HotPink == sourcePixels[50, 50], "[50, 50] wrong"); - - Assert.True(Rgba32.Blue == sourcePixels[2, 2], "[2, 2] wrong"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonImage() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (Image brushImage = TestFile.Create(TestImages.Bmp.Car).CreateRgba32Image()) - using (var image = new Image(500, 500)) - { - var brush = new ImageBrush(brushImage); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.FillPolygon(brush, simplePath)); - image.Save($"{path}/Image.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.FillPolygon(color, simplePath)); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledRectangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Fill( - Rgba32.HotPink, - new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledTriangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - using (var image = new Image(100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30))); - image.Save($"{path}/Triangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.Blue, sourcePixels[30, 65]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledSeptagon() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, - new RegularPolygon(50, 50, 7, 30, -(float)Math.PI))); - image.Save($"{path}/Septagon.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledEllipse() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x - .Fill(Rgba32.HotPink, new EllipsePolygon(50, 50, 30, 50) - .Rotate((float)(Math.PI / 3)))); - image.Save($"{path}/ellipse.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedBySquareWithCornerClipped() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 200, 200)) - { - image.Mutate(x => x - .Fill(Rgba32.Blue) - .FillPolygon(Rgba32.HotPink, new SixLabors.Primitives.PointF[] - { - new Vector2( 8, 8 ), - new Vector2( 64, 8 ), - new Vector2( 64, 64 ), - new Vector2( 120, 64 ), - new Vector2( 120, 120 ), - new Vector2( 8, 120 ) - })); - image.Save($"{path}/clipped-corner.png"); - } - } - } -} diff --git a/tests/Images/External b/tests/Images/External index 5036d47ec2..0edeb078b9 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 5036d47ec2393d90efb6f3864d828e2e4381947f +Subproject commit 0edeb078b9d9f9c8be016ca514a3a625c4768bd6 From 680156ad0c4236fe79b707bd36ed513b015ba515 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 03:00:05 +0200 Subject: [PATCH 06/27] DrawPolygonTests, DrawLinesTests --- .../Drawing/DrawLinesTests.cs | 100 +++++++++ .../Drawing/DrawPolygonTests.cs | 43 ++++ tests/ImageSharp.Tests/Drawing/LineTests.cs | 193 ------------------ .../ImageSharp.Tests/Drawing/PolygonTests.cs | 102 --------- tests/Images/External | 2 +- 5 files changed, 144 insertions(+), 296 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs create mode 100644 tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/LineTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/PolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs new file mode 100644 index 0000000000..c225b921e6 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs @@ -0,0 +1,100 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawLinesTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] + public void DrawLines_Simple(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = new Pen(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + public void DrawLines_Dash(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.Dash(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "LightGreen", 1f, 5, false)] + public void DrawLines_Dot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.Dot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Yellow", 1f, 5, false)] + public void DrawLines_DashDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.DashDot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Black", 1f, 5, false)] + public void DrawLines_DashDotDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.DashDotDot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + + private static void DrawLinesImpl( + TestImageProvider provider, + string colorName, + float alpha, + float thickness, + bool antialias, + Pen pen) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; + + provider.RunValidatingProcessorTest( + c => c.DrawLines(options, pen, simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + + } +} diff --git a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs new file mode 100644 index 0000000000..8a0f256670 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs @@ -0,0 +1,43 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; +using SixLabors.ImageSharp.Processing; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] + public void DrawPolygon(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; + + provider.RunValidatingProcessorTest( + c => c.DrawPolygon(options, color.ToPixel(), thickness, simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs deleted file mode 100644 index 1cc0fd1a40..0000000000 --- a/tests/ImageSharp.Tests/Drawing/LineTests.cs +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class LineTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPath() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPath_NoAntialias() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - new GraphicsOptions(false), - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple_noantialias.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashed() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.Dash(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/Dashed.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDotted() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.Dot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/Dot.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashDot() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.DashDot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/DashDot.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashDotDot() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/DashDotDot.png"); - } - - [Fact] - public void ImageShouldBeOverlayedPathWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - color, - 10, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = - new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[11, 11]); - - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - - [Fact] - public void ImageShouldBeOverlayedByPathOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - Rgba32.HotPink, - 10, - new Vector2(10, 10), - new Vector2(200, 10), - new Vector2(200, 150), - new Vector2(10, 150))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.Blue, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs deleted file mode 100644 index febb39c20d..0000000000 --- a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; -using SixLabors.ImageSharp.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class PolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawPolygon( - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[9, 9]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - PointF[] simplePath = { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawPolygon(color, 10, simplePath)); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - Rgba32 mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[9, 9]); - - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByRectangleOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[8, 8]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - } -} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 0edeb078b9..4fe9334aa8 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 0edeb078b9d9f9c8be016ca514a3a625c4768bd6 +Subproject commit 4fe9334aa8898f67b6e3df94bc00867645c3e709 From 473fd02be7693f63ee5a77c3c44b52afd7fc59ee Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 03:22:21 +0200 Subject: [PATCH 07/27] DrawBeziersTests, DrawComplexPolygonTests --- .../Drawing/DrawBezierTests.cs | 102 +++------ .../Drawing/DrawComplexPolygonTests.cs | 70 ++++++ .../Drawing/LineComplexPolygonTests.cs | 201 ------------------ tests/Images/External | 2 +- 4 files changed, 100 insertions(+), 275 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index d82221ca67..0f29728c9f 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.Memory; @@ -11,82 +12,37 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { + [GroupOutput("Drawing")] public class DrawBezierTests { - [Fact] - public void ImageShouldBeOverlayedByBezierLine() + public static readonly TheoryData DrawPathData = new TheoryData + { + { "White", 255, 1.5f }, + { "Red", 255, 3 }, + { "HotPink", 255, 5 }, + { "HotPink", 150, 5 }, + { "White", 255, 15 }, + }; + + [Theory] + [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] + public void DrawBeziers(TestImageProvider provider, string colorName, byte alpha, float thickness) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); - using (var image = new Image(350, 450)) - { - image.Mutate(x => x.BackgroundColor(Color.Blue)); - image.Mutate( - x => x.DrawBeziers( - Rgba32.HotPink, - 5, - new SixLabors.Primitives.PointF[] - { - new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) - })); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - //top of curve - Assert.Equal(Rgba32.HotPink, sourcePixels[138, 115]); - - //start points - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 395]); - Assert.Equal(Rgba32.HotPink, sourcePixels[300, 395]); - - //curve points should not be never be set - Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); - Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); - - // inside shape should be empty - Assert.Equal(Rgba32.Blue, sourcePixels[200, 250]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedBezierLineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(350, 450)) - { - image.Mutate(x => x.BackgroundColor(Color.Blue)); - image.Mutate( - x => x.DrawBeziers( - color, - 10, - new SixLabors.Primitives.PointF[] - { - new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) - })); - image.Save($"{path}/Opacity.png"); - - //shift background color towards foreground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - // top of curve - Assert.Equal(mergedColor, sourcePixels[138, 115]); - - // start points - Assert.Equal(mergedColor, sourcePixels[10, 395]); - Assert.Equal(mergedColor, sourcePixels[300, 395]); - - // curve points should not be never be set - Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); - Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); - - // inside shape should be empty - Assert.Equal(Rgba32.Blue, sourcePixels[200, 250]); - } + var points = new SixLabors.Primitives.PointF[] + { + new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) + }; + Rgba32 rgba = TestUtils.GetColorByName(colorName); + rgba.A = alpha; + Color color = rgba; + + FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; + + provider.RunValidatingProcessorTest( x => x.DrawBeziers(color.ToPixel(), 5f, points), + testDetails, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); } } } diff --git a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs new file mode 100644 index 0000000000..b6e105a199 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs @@ -0,0 +1,70 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawComplexPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, true, false, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, true, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, true)] + public void DrawComplexPolygon(TestImageProvider provider, bool overlap, bool transparent, bool dashed) + where TPixel :struct, IPixel + { + var simplePath = new Polygon(new LinearLineSegment( + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300))); + + var hole1 = new Polygon(new LinearLineSegment( + new Vector2(37, 85), + overlap ? new Vector2(130, 40) : new Vector2(93, 85), + new Vector2(65, 137))); + IPath clipped = simplePath.Clip(hole1); + + Rgba32 colorRgba = Rgba32.White; + if (transparent) + { + colorRgba.A = 150; + } + + Color color = colorRgba; + + string testDetails = ""; + if (overlap) + { + testDetails += "_Overlap"; + } + + if (transparent) + { + testDetails += "_Transparent"; + } + + if (dashed) + { + testDetails += "_Dashed"; + } + + Pen pen = dashed ? Pens.Dash(color.ToPixel(), 5f) : Pens.Solid(color.ToPixel(), 5f); + + provider.RunValidatingProcessorTest( + x => x.Draw(pen, clipped), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs deleted file mode 100644 index 06961bec4b..0000000000 --- a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class LineComplexPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[37, 85]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[93, 85]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[65, 137]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineNoOverlapping() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(207, 25), - new Vector2(263, 25), - new Vector2(235, 57))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleVanishHole.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - - //Assert.Equal(Color.HotPink, sourcePixels[37, 85]); - - //Assert.Equal(Color.HotPink, sourcePixels[93, 85]); - - //Assert.Equal(Color.HotPink, sourcePixels[65, 137]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineOverlapping() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(130, 40), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleOverlapping.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - Assert.Equal(Rgba32.Blue, sourcePixels[130, 41]); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineDashed() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))); - image.Save($"{path}/Dashed.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(color, 5, simplePath.Clip(hole1))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[10, 10]); - Assert.Equal(mergedColor, sourcePixels[200, 150]); - Assert.Equal(mergedColor, sourcePixels[50, 300]); - Assert.Equal(mergedColor, sourcePixels[37, 85]); - Assert.Equal(mergedColor, sourcePixels[93, 85]); - Assert.Equal(mergedColor, sourcePixels[65, 137]); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - } -} diff --git a/tests/Images/External b/tests/Images/External index 4fe9334aa8..55c250ab80 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 4fe9334aa8898f67b6e3df94bc00867645c3e709 +Subproject commit 55c250ab80f7f9fc26208b9b9d9590cbe8012446 From a910005db0c2862d81d9b203d666c25d9e458dc9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 13:44:53 +0200 Subject: [PATCH 08/27] fix merge issues --- src/ImageSharp/Color/Color.Conversions.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 3123d89e96..16d673d85d 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -62,12 +62,19 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] public Color(Vector4 vector) => this.data = new Rgba64(vector); - [MethodImpl(InliningOptions.ShortMethod)] + /// + /// Converts a to . + /// + /// The . + /// The . + public static explicit operator Vector4(Color color) => color.data.ToVector4(); + /// /// Converts an to . /// /// The . /// The . + [MethodImpl(InliningOptions.ShortMethod)] public static explicit operator Color(Vector4 source) => new Color(source); [MethodImpl(InliningOptions.ShortMethod)] @@ -84,12 +91,5 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] internal Bgr24 ToBgr24() => this.data.ToBgr24(); - - /// - /// Converts a to . - /// - /// The . - /// The . - public static explicit operator Vector4(Color color) => color.data.ToVector4(); } } \ No newline at end of file From 21f221ec29aedb13d0679d2bc7b71332c557c944 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 14:37:02 +0200 Subject: [PATCH 09/27] DrawImageTests: add tolerance to make all test configurations happy --- tests/ImageSharp.Tests/Drawing/DrawImageTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index f4e9b7b450..70879e6feb 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -91,7 +91,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing } image.DebugSave(provider, testInfo, encoder: encoder); - image.CompareToReferenceOutput(provider, testInfo); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), + provider, + testInfo); } } @@ -146,7 +148,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing image.Mutate(x => x.DrawImage(blend, position, .75F)); image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); - image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.002f), + provider, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); } } From 2bff82367c3b7e597a7532db6ad6612063409473 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 20:39:01 +0200 Subject: [PATCH 10/27] started the refactor --- .../Processing/DrawingHelpers.cs | 19 ++++++++++++ src/ImageSharp.Drawing/Processing/IBrush.cs | 9 ++++-- src/ImageSharp.Drawing/Processing/IPen.cs | 16 +++------- .../Processing/PatternBrush{TPixel}.cs | 30 +++++++++++-------- .../Processing/SolidBrush{TPixel}.cs | 18 +++++------ src/ImageSharp/Color/Color.Conversions.cs | 3 ++ 6 files changed, 59 insertions(+), 36 deletions(-) create mode 100644 src/ImageSharp.Drawing/Processing/DrawingHelpers.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs new file mode 100644 index 0000000000..314b65f7e7 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs @@ -0,0 +1,19 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; + +namespace SixLabors.ImageSharp.Processing +{ + internal static class DrawingHelpers + { + public static DenseMatrix ToPixelMatrix(this DenseMatrix colorMatrix, Configuration configuration) + where TPixel : struct, IPixel + { + DenseMatrix result = new DenseMatrix(colorMatrix.Columns, colorMatrix.Rows); + Color.ToPixel(configuration, colorMatrix.Span, result.Span); + return result; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs index a3c94a1b5a..aa8c25b950 100644 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ b/src/ImageSharp.Drawing/Processing/IBrush.cs @@ -14,8 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// A brush is a simple class that will return an that will perform the /// logic for converting a pixel location to a . /// - public interface IBrush - where TPixel : struct, IPixel + public interface IBrush { /// /// Creates the applicator for this brush. @@ -30,6 +29,10 @@ namespace SixLabors.ImageSharp.Processing /// The when being applied to things like shapes would usually be the /// bounding box of the shape not necessarily the bounds of the whole image /// - BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options); + BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs index 6f63dcfd0f..b9e359d601 100644 --- a/src/ImageSharp.Drawing/Processing/IPen.cs +++ b/src/ImageSharp.Drawing/Processing/IPen.cs @@ -7,23 +7,15 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing { /// - /// Interface representing a Pen + /// Interface representing the pattern and size of the stroke to apply with a Pen. /// - /// The type of the color. - public interface IPen : IPen - where TPixel : struct, IPixel + public interface IPen { /// /// Gets the stroke fill. /// - IBrush StrokeFill { get; } - } - - /// - /// Interface representing the pattern and size of the stroke to apply with a Pen. - /// - public interface IPen - { + IBrush StrokeFill { get; } + /// /// Gets the width to apply to the stroke /// diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 20161b517d..249383f3b1 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -35,13 +35,12 @@ namespace SixLabors.ImageSharp.Processing /// /// /// The pixel format. - public class PatternBrush : IBrush - where TPixel : struct, IPixel + public class PatternBrush : IBrush { /// /// The pattern. /// - private readonly DenseMatrix pattern; + private readonly DenseMatrix pattern; private readonly DenseMatrix patternVector; /// @@ -50,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing /// Color of the fore. /// Color of the back. /// The pattern. - public PatternBrush(TPixel foreColor, TPixel backColor, bool[,] pattern) + public PatternBrush(Color foreColor, Color backColor, bool[,] pattern) : this(foreColor, backColor, new DenseMatrix(pattern)) { } @@ -61,11 +60,11 @@ namespace SixLabors.ImageSharp.Processing /// Color of the fore. /// Color of the back. /// The pattern. - internal PatternBrush(TPixel foreColor, TPixel backColor, in DenseMatrix pattern) + internal PatternBrush(Color foreColor, Color backColor, in DenseMatrix pattern) { var foreColorVector = foreColor.ToVector4(); var backColorVector = backColor.ToVector4(); - this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); + this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); this.patternVector = new DenseMatrix(pattern.Columns, pattern.Rows); for (int i = 0; i < pattern.Data.Length; i++) { @@ -86,19 +85,25 @@ namespace SixLabors.ImageSharp.Processing /// Initializes a new instance of the class. /// /// The brush. - internal PatternBrush(PatternBrush brush) + internal PatternBrush(PatternBrush brush) { this.pattern = brush.pattern; this.patternVector = brush.patternVector; } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) => new PatternBrushApplicator(source, this.pattern, this.patternVector, options); + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel => + new PatternBrushApplicator(source, this.pattern, this.patternVector, options); /// /// The pattern brush applicator. /// - private class PatternBrushApplicator : BrushApplicator + private class PatternBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The pattern. @@ -107,16 +112,17 @@ namespace SixLabors.ImageSharp.Processing private readonly DenseMatrix patternVector; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// The pattern. /// The patternVector. /// The options - public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) + public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) : base(source, options) { - this.pattern = pattern; + this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); + Color.ToPixel(source.Configuration, pattern.Data, this.pattern.Data); this.patternVector = patternVector; } diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs index 20a6833c40..75ca5aa7e8 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs @@ -15,20 +15,18 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of a solid brush for painting solid color areas. /// - /// The pixel format. - public class SolidBrush : IBrush - where TPixel : struct, IPixel + public class SolidBrush : IBrush { /// /// The color to paint. /// - private readonly TPixel color; + private readonly Color color; /// /// Initializes a new instance of the class. /// /// The color. - public SolidBrush(TPixel color) + public SolidBrush(Color color) { this.color = color; } @@ -39,18 +37,20 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// - public TPixel Color => this.color; + public Color Color => this.color; /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + where TPixel : struct, IPixel { - return new SolidBrushApplicator(source, this.color, options); + return new SolidBrushApplicator(source, this.color.ToPixel(), options); } /// /// The solid brush applicator. /// - private class SolidBrushApplicator : BrushApplicator + private class SolidBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 16d673d85d..a6e0717f48 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -91,5 +91,8 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] internal Bgr24 ToBgr24() => this.data.ToBgr24(); + + [MethodImpl(InliningOptions.ShortMethod)] + internal Vector4 ToVector4() => this.data.ToVector4(); } } \ No newline at end of file From 73f9116a46b5931003339e729e92758b55e353a2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:08:19 +0200 Subject: [PATCH 11/27] Pen, Brush & Processors refactored --- src/ImageSharp.Drawing/Processing/Brushes.cs | 120 ++++----- .../Processing/DrawBezierExtensions.cs | 44 ++-- .../Processing/ImageBrush{TPixel}.cs | 28 +-- .../Processing/PatternBrush{TPixel}.cs | 11 +- src/ImageSharp.Drawing/Processing/Pens.cs | 50 +--- .../Processing/Pen{TPixel}.cs | 18 +- .../Processors/Drawing/FillProcessor.cs | 57 +++-- .../Processors/Drawing/FillRegionProcessor.cs | 63 +++-- .../Processors/Text/DrawTextProcessor.cs | 55 ++++- .../Processing/RecolorBrush{TPixel}.cs | 29 ++- src/ImageSharp/GraphicsOptions.cs | 231 +++++++++--------- 11 files changed, 356 insertions(+), 350 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Brushes.cs b/src/ImageSharp.Drawing/Processing/Brushes.cs index c5e7a3e9ff..bd73e1f1b6 100644 --- a/src/ImageSharp.Drawing/Processing/Brushes.cs +++ b/src/ImageSharp.Drawing/Processing/Brushes.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing /// /// A collection of methods for creating generic brushes. /// - /// A New + /// A New public static class Brushes { /// @@ -94,163 +94,131 @@ namespace SixLabors.ImageSharp.Processing /// Create as brush that will paint a solid color /// /// The color. - /// The pixel format. - /// A New - public static SolidBrush Solid(TPixel color) - where TPixel : struct, IPixel - => new SolidBrush(color); + /// A New + public static SolidBrush Solid(Color color) => new SolidBrush(color); /// /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Percent10(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, Percent10Pattern); + /// A New + public static PatternBrush Percent10(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, Percent10Pattern); /// /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Percent10(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, Percent10Pattern); + /// A New + public static PatternBrush Percent10(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, Percent10Pattern); /// /// Create as brush that will paint a Percent20 Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Percent20(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, Percent20Pattern); + /// A New + public static PatternBrush Percent20(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, Percent20Pattern); /// /// Create as brush that will paint a Percent20 Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Percent20(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, Percent20Pattern); + /// A New + public static PatternBrush Percent20(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, Percent20Pattern); /// /// Create as brush that will paint a Horizontal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Horizontal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, HorizontalPattern); + /// A New + public static PatternBrush Horizontal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, HorizontalPattern); /// /// Create as brush that will paint a Horizontal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Horizontal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, HorizontalPattern); + /// A New + public static PatternBrush Horizontal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, HorizontalPattern); /// /// Create as brush that will paint a Min Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Min(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, MinPattern); + /// A New + public static PatternBrush Min(Color foreColor) => new PatternBrush(foreColor, Color.Transparent, MinPattern); /// /// Create as brush that will paint a Min Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Min(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, MinPattern); + /// A New + public static PatternBrush Min(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, MinPattern); /// /// Create as brush that will paint a Vertical Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Vertical(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, VerticalPattern); + /// A New + public static PatternBrush Vertical(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, VerticalPattern); /// /// Create as brush that will paint a Vertical Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Vertical(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, VerticalPattern); + /// A New + public static PatternBrush Vertical(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, VerticalPattern); /// /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush ForwardDiagonal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, ForwardDiagonalPattern); + /// A New + public static PatternBrush ForwardDiagonal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, ForwardDiagonalPattern); /// /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush ForwardDiagonal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); + /// A New + public static PatternBrush ForwardDiagonal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); /// /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush BackwardDiagonal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, BackwardDiagonalPattern); + /// A New + public static PatternBrush BackwardDiagonal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, BackwardDiagonalPattern); /// /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush BackwardDiagonal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); + /// A New + public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs index 782f5d4d73..991c01293a 100644 --- a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs @@ -15,80 +15,80 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) + + => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) + + => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawBeziers(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) + + => source.DrawBeziers(new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawBeziers(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) + + => source.DrawBeziers(options, new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The type of the color. + /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) + => source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The type of the color. + /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) + => source.Draw(pen, new Path(new CubicBezierLineSegment(points))); } } diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs index cfb3b2ea4f..d5ec1123d7 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs @@ -15,40 +15,38 @@ namespace SixLabors.ImageSharp.Processing /// Provides an implementation of an image brush for painting images within areas. /// /// The pixel format. - public class ImageBrush : IBrush - where TPixel : struct, IPixel + public class ImageBrush : IBrush { /// /// The image to paint. /// - private readonly ImageFrame image; + private readonly Image image; /// /// Initializes a new instance of the class. /// /// The image. - public ImageBrush(ImageFrame image) + public ImageBrush(Image image) { this.image = image; } - /// - /// Initializes a new instance of the class. - /// - /// The image. - public ImageBrush(Image image) - : this(image.Frames.RootFrame) + /// + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel { + Image specificImage = (Image)this.image; + return new ImageBrushApplicator(source, specificImage.Frames.RootFrame, region, options); } - /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new ImageBrushApplicator(source, this.image, region, options); - /// /// The image brush applicator. /// - private class ImageBrushApplicator : BrushApplicator + private class ImageBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The source image. diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 249383f3b1..0e66756721 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -97,7 +97,11 @@ namespace SixLabors.ImageSharp.Processing RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel => - new PatternBrushApplicator(source, this.pattern, this.patternVector, options); + new PatternBrushApplicator( + source, + this.pattern.ToPixelMatrix(source.Configuration), + this.patternVector, + options); /// /// The pattern brush applicator. @@ -118,11 +122,10 @@ namespace SixLabors.ImageSharp.Processing /// The pattern. /// The patternVector. /// The options - public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) + public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) : base(source, options) { - this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); - Color.ToPixel(source.Configuration, pattern.Data, this.pattern.Data); + this.pattern = pattern; this.patternVector = patternVector; } diff --git a/src/ImageSharp.Drawing/Processing/Pens.cs b/src/ImageSharp.Drawing/Processing/Pens.cs index 90253a3cb8..4b8f478c92 100644 --- a/src/ImageSharp.Drawing/Processing/Pens.cs +++ b/src/ImageSharp.Drawing/Processing/Pens.cs @@ -21,109 +21,79 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Solid(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width); + public static Pen Solid(Color color, float width) => new Pen(color, width); /// /// Create a solid pen with out any drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Solid(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width); + public static Pen Solid(IBrush brush, float width) => new Pen(brush, width); /// /// Create a pen with a 'Dash' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Dash(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashedPattern); + public static Pen Dash(Color color, float width) => new Pen(color, width, DashedPattern); /// /// Create a pen with a 'Dash' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Dash(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashedPattern); + public static Pen Dash(IBrush brush, float width) => new Pen(brush, width, DashedPattern); /// /// Create a pen with a 'Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Dot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DottedPattern); + public static Pen Dot(Color color, float width) => new Pen(color, width, DottedPattern); /// /// Create a pen with a 'Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Dot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DottedPattern); + public static Pen Dot(IBrush brush, float width) => new Pen(brush, width, DottedPattern); /// /// Create a pen with a 'Dash Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashDotPattern); + public static Pen DashDot(Color color, float width) => new Pen(color, width, DashDotPattern); /// /// Create a pen with a 'Dash Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashDotPattern); + public static Pen DashDot(IBrush brush, float width) => new Pen(brush, width, DashDotPattern); /// /// Create a pen with a 'Dash Dot Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDotDot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashDotDotPattern); + public static Pen DashDotDot(Color color, float width) => new Pen(color, width, DashDotDotPattern); /// /// Create a pen with a 'Dash Dot Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDotDot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashDotDotPattern); + public static Pen DashDotDot(IBrush brush, float width) => new Pen(brush, width, DashDotDotPattern); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs index 26c21a0e51..922394946a 100644 --- a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs @@ -9,7 +9,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides a pen that can apply a pattern to a line with a set brush and thickness /// - /// The type of the color. /// /// The pattern will be in to the form of new float[]{ 1f, 2f, 0.5f} this will be /// converted into a pattern that is 3.5 times longer that the width with 3 sections @@ -18,8 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// section 3 will be width/2 long and will be filled /// the the pattern will immediately repeat without gap. /// - public class Pen : IPen - where TPixel : struct, IPixel + public class Pen : IPen { private readonly float[] pattern; @@ -29,8 +27,8 @@ namespace SixLabors.ImageSharp.Processing /// The color. /// The width. /// The pattern. - public Pen(TPixel color, float width, float[] pattern) - : this(new SolidBrush(color), width, pattern) + public Pen(Color color, float width, float[] pattern) + : this(new SolidBrush(color), width, pattern) { } @@ -40,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// The brush. /// The width. /// The pattern. - public Pen(IBrush brush, float width, float[] pattern) + public Pen(IBrush brush, float width, float[] pattern) { this.StrokeFill = brush; this.StrokeWidth = width; @@ -52,8 +50,8 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// The width. - public Pen(TPixel color, float width) - : this(new SolidBrush(color), width) + public Pen(Color color, float width) + : this(new SolidBrush(color), width) { } @@ -62,13 +60,13 @@ namespace SixLabors.ImageSharp.Processing /// /// The brush. /// The width. - public Pen(IBrush brush, float width) + public Pen(IBrush brush, float width) : this(brush, width, Pens.EmptyPattern) { } /// - public IBrush StrokeFill { get; } + public IBrush StrokeFill { get; } /// public float StrokeWidth { get; } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index ed6c869511..8ea1c48cc2 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -13,6 +13,26 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + public class FillProcessor : IImageProcessor + { + public FillProcessor(IBrush brush, GraphicsOptions options) + { + this.Brush = brush; + this.Options = options; + } + + public IBrush Brush { get; } + + public GraphicsOptions Options { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new FillProcessor(this); + } + } + /// /// Using the brush as a source of pixels colors blends the brush color with source. /// @@ -20,21 +40,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing internal class FillProcessor : ImageProcessor where TPixel : struct, IPixel { - /// - /// The brush. - /// - private readonly IBrush brush; - private readonly GraphicsOptions options; - - /// - /// Initializes a new instance of the class. - /// - /// The brush to source pixel colors from. - /// The options - public FillProcessor(IBrush brush, GraphicsOptions options) + private readonly FillProcessor definition; + + public FillProcessor(FillProcessor definition) { - this.brush = brush; - this.options = options; + this.definition = definition; } /// @@ -55,11 +65,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + IBrush brush = this.definition.Brush; + GraphicsOptions options = this.definition.Options; + // If there's no reason for blending, then avoid it. - if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) + if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) { ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + TPixel colorPixel = solidBrush.Color.ToPixel(); + ParallelHelper.IterateRows( workingRect, parallelSettings, @@ -67,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { for (int y = rows.Min; y < rows.Max; y++) { - source.GetPixelRowSpan(y).Slice(minX, width).Fill(solidBrush.Color); + source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); } }); } @@ -85,10 +100,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - using (BrushApplicator applicator = this.brush.CreateApplicator( + using (BrushApplicator applicator = brush.CreateApplicator( source, sourceRectangle, - this.options)) + options)) { amount.GetSpan().Fill(1f); @@ -109,16 +124,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } } - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) { - solidBrush = this.brush as SolidBrush; + solidBrush = this.definition.Brush as SolidBrush; if (solidBrush == null) { return false; } - return this.options.IsOpaqueColorWithoutBlending(solidBrush.Color); + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs index 550c021caa..3653102efa 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs @@ -13,24 +13,15 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { - /// - /// Using a brush and a shape fills shape with contents of brush the - /// - /// The type of the color. - /// - internal class FillRegionProcessor : ImageProcessor - where TPixel : struct, IPixel + public class FillRegionProcessor : IImageProcessor { - private const float AntialiasFactor = 1f; - private const int DrawPadding = 1; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The details how to fill the region of interest. /// The region of interest to be filled. /// The configuration options. - public FillRegionProcessor(IBrush brush, Region region, GraphicsOptions options) + public FillRegionProcessor(IBrush brush, Region region, GraphicsOptions options) { this.Region = region; this.Brush = brush; @@ -40,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Gets the brush. /// - public IBrush Brush { get; } + public IBrush Brush { get; } /// /// Gets the region that this processor applies to. @@ -55,10 +46,35 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// public GraphicsOptions Options { get; } + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new FillRegionProcessor(this); + } + } + + /// + /// Using a brush and a shape fills shape with contents of brush the + /// + /// The type of the color. + /// + internal class FillRegionProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillRegionProcessor definition; + + public FillRegionProcessor(FillRegionProcessor definition) + { + this.definition = definition; + } + /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - Region region = this.Region; + GraphicsOptions options = this.definition.Options; + IBrush brush = this.definition.Brush; + Region region = this.definition.Region; Rectangle rect = region.Bounds; // Align start/end positions. @@ -84,17 +100,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing // 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 align with the pixel grid. float offset = 0.5f; - if (this.Options.Antialias) + if (options.Antialias) { offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = this.Options.AntialiasSubpixelDepth; + subpixelCount = options.AntialiasSubpixelDepth; if (subpixelCount < 4) { subpixelCount = 4; } } - using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options)) + using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) { int scanlineWidth = maxX - minX; using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) @@ -107,7 +123,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing Span buffer = bBuffer.GetSpan(); Span scanline = bScanline.GetSpan(); - bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; for (int y = minY; y < maxY; y++) { @@ -168,7 +185,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing if (scanlineDirty) { - if (!this.Options.Antialias) + if (!options.Antialias) { bool hasOnes = false; bool hasZeros = false; @@ -190,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { if (hasOnes) { - source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrush.Color); + source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); } continue; @@ -204,16 +221,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } } - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) { - solidBrush = this.Brush as SolidBrush; + solidBrush = this.definition.Brush as SolidBrush; if (solidBrush == null) { return false; } - return this.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 266d842bfa..016cf56dea 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -15,17 +15,10 @@ using SixLabors.Shapes; namespace SixLabors.ImageSharp.Processing.Processors.Text { - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class DrawTextProcessor : ImageProcessor - where TPixel : struct, IPixel + public class DrawTextProcessor : IImageProcessor { - private CachingGlyphRenderer textRenderer; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The options /// The text we want to render @@ -33,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// The brush to source pixel colors from. /// The pen to outline text with. /// The location on the image to start drawing the text from. - public DrawTextProcessor(TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) + public DrawTextProcessor(TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) { Guard.NotNull(text, nameof(text)); Guard.NotNull(font, nameof(font)); @@ -54,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// /// Gets the brush. /// - public IBrush Brush { get; } + public IBrush Brush { get; } /// /// Gets the options @@ -69,7 +62,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// /// Gets the pen used for outlining the text, if Null then we will not outline /// - public IPen Pen { get; } + public IPen Pen { get; } /// /// Gets the font used to render the text. @@ -81,6 +74,42 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// public PointF Location { get; } + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + throw new NotImplementedException(); + } + } + + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class DrawTextProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private CachingGlyphRenderer textRenderer; + + private readonly DrawTextProcessor definition; + + public DrawTextProcessor(DrawTextProcessor definition) + { + this.definition = definition; + } + + private TextGraphicsOptions Options => this.definition.Options; + + private Font Font => this.definition.Font; + + private PointF Location => this.definition.Location; + + private string Text => this.definition.Text; + + private IPen Pen => this.definition.Pen; + + private IBrush Brush => this.definition.Brush; + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) { base.BeforeImageApply(source, sourceRectangle); @@ -115,7 +144,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text Draw(this.textRenderer.FillOperations, this.Brush); Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); - void Draw(List operations, IBrush brush) + void Draw(List operations, IBrush brush) { if (operations?.Count > 0) { diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs index 09a1ff71fb..ff098dce7c 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs @@ -16,16 +16,15 @@ namespace SixLabors.ImageSharp.Processing /// Provides an implementation of a brush that can recolor an image /// /// The pixel format. - public class RecolorBrush : IBrush - where TPixel : struct, IPixel + public class RecolorBrush : IBrush { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the source. /// Color of the target. /// The threshold as a value between 0 and 1. - public RecolorBrush(TPixel sourceColor, TPixel targetColor, float threshold) + public RecolorBrush(Color sourceColor, Color targetColor, float threshold) { this.SourceColor = sourceColor; this.Threshold = threshold; @@ -43,23 +42,33 @@ namespace SixLabors.ImageSharp.Processing /// /// The color of the source. /// - public TPixel SourceColor { get; } + public Color SourceColor { get; } /// /// Gets the target color. /// - public TPixel TargetColor { get; } + public Color TargetColor { get; } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel { - return new RecolorBrushApplicator(source, this.SourceColor, this.TargetColor, this.Threshold, options); + return new RecolorBrushApplicator( + source, + this.SourceColor.ToPixel(), + this.TargetColor.ToPixel(), + this.Threshold, + options); } /// /// The recolor brush applicator. /// - private class RecolorBrushApplicator : BrushApplicator + private class RecolorBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The source color. @@ -79,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing private readonly TPixel targetColorPixel; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// Color of the source. diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 2d20c17732..537418de24 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -1,141 +1,141 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Options for influencing the drawing functions. - /// - public struct GraphicsOptions - { - /// - /// Represents the default . - /// - public static readonly GraphicsOptions Default = new GraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Options for influencing the drawing functions. + /// + public struct GraphicsOptions + { + /// + /// Represents the default . + /// + public static readonly GraphicsOptions Default = new GraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + private PixelColorBlendingMode colorBlendingMode; - private PixelAlphaCompositionMode alphaCompositionMode; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public GraphicsOptions(bool enableAntialiasing) - { + private PixelAlphaCompositionMode alphaCompositionMode; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public GraphicsOptions(bool enableAntialiasing) + { this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, float opacity) + /// blending percentage to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) + /// color blending mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = blending; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. /// blending percentage to apply to the drawing operation /// color blending mode to apply to the drawing operation - /// alpha composition mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) + /// alpha composition mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = blending; - this.alphaCompositionMode = composition; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias - { - get => this.antialias ?? true; - set => this.antialias = value; - } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth - { - get => this.antialiasSubpixelDepth ?? 16; - set => this.antialiasSubpixelDepth = value; - } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage - { - get => (this.blendPercentage ?? 1).Clamp(0, 1); - set => this.blendPercentage = value; - } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending mode to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode - { - get => this.colorBlendingMode; - set => this.colorBlendingMode = value; + this.alphaCompositionMode = composition; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode - { - get => this.alphaCompositionMode; - set => this.alphaCompositionMode = value; + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias + { + get => this.antialias ?? true; + set => this.antialias = value; + } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth + { + get => this.antialiasSubpixelDepth ?? 16; + set => this.antialiasSubpixelDepth = value; + } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage + { + get => (this.blendPercentage ?? 1).Clamp(0, 1); + set => this.blendPercentage = value; + } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending mode to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode + { + get => this.colorBlendingMode; + set => this.colorBlendingMode = value; + } + + /// + /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode + { + get => this.alphaCompositionMode; + set => this.alphaCompositionMode = value; } /// @@ -149,8 +149,7 @@ namespace SixLabors.ImageSharp /// filling with a solid color, the blending can be avoided by a plain color replacement. /// This method can be useful for such processors to select the fast path. /// - internal bool IsOpaqueColorWithoutBlending(TPixel color) - where TPixel : struct, IPixel + internal bool IsOpaqueColorWithoutBlending(Color color) { if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) { @@ -174,6 +173,6 @@ namespace SixLabors.ImageSharp } return true; - } - } + } + } } \ No newline at end of file From b902e6c99c0bee7f54666c618c699526c353940e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:27:04 +0200 Subject: [PATCH 12/27] ImageSharp.Drawing compiles --- .../Processing/ColorStop{TPixel}.cs | 10 +- .../Processing/DrawBezierExtensions.cs | 61 +++++++----- .../Processing/DrawLineExtensions.cs | 61 +++++++----- .../DrawPathCollectionExtensions.cs | 57 ++++++----- .../Processing/DrawPathExtensions.cs | 44 ++++----- .../Processing/DrawPolygonExtensions.cs | 61 +++++++----- .../Processing/DrawRectangleExtensions.cs | 58 +++++++----- .../Processing/DrawTextExtensions.cs | 94 ++++++++++++------- .../EllipticGradientBrush{TPixel}.cs | 21 ++--- .../Processing/FillPathBuilderExtensions.cs | 36 ++++--- .../FillPathCollectionExtensions.cs | 36 ++++--- .../Processing/FillPathExtensions.cs | 28 +++--- .../Processing/FillPolygonExtensions.cs | 38 ++++---- .../Processing/FillRectangleExtensions.cs | 34 +++---- .../Processing/FillRegionExtensions.cs | 52 +++++----- .../Processing/GradientBrushBase{TPixel}.cs | 38 ++++---- .../Processing/LinearGradientBrush{TPixel}.cs | 19 ++-- .../Processing/PatternBrush{TPixel}.cs | 7 +- .../Processing/RadialGradientBrush{TPixel}.cs | 22 ++--- src/ImageSharp/GraphicsOptions.cs | 1 - 20 files changed, 442 insertions(+), 336 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs index 7fd0ba7cd3..aee559469f 100644 --- a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs @@ -10,17 +10,15 @@ namespace SixLabors.ImageSharp.Processing /// /// A struct that defines a single color stop. /// - /// The pixel format. [DebuggerDisplay("ColorStop({Ratio} -> {Color}")] - public struct ColorStop - where TPixel : struct, IPixel + public readonly struct ColorStop { /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// Where should it be? 0 is at the start, 1 at the end of the Gradient. /// What color should be used at that point? - public ColorStop(float ratio, TPixel color) + public ColorStop(float ratio, in Color color) { this.Ratio = ratio; this.Color = color; @@ -34,6 +32,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the color to be used. /// - public TPixel Color { get; } + public Color Color { get; } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs index 991c01293a..85addd5f2c 100644 --- a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - - => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - - => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - - => source.DrawBeziers(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawBeziers(new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - - => source.DrawBeziers(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawBeziers(options, new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - - => source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) - - => source.Draw(pen, new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(pen, new Path(new CubicBezierLineSegment(points))); } } diff --git a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs index 9084b30efe..b7b419be61 100644 --- a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawLines(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawLines(new SolidBrush(color), thickness, points); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The .> - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawLines(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawLines(options, new SolidBrush(color), thickness, points); /// /// Draws the provided Points as an open Linear path with the supplied pen /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, pen, new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path with the supplied pen /// - /// The type of the color. /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(pen, new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(pen, new Path(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs index 0d3abf297e..79b4fd0a80 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs @@ -14,14 +14,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPathCollection paths) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + IPathCollection paths) { foreach (IPath path in paths) { @@ -34,67 +36,76 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, paths); + public static IImageProcessingContext + Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) => + source.Draw(GraphicsOptions.Default, pen, paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shapes. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + IPathCollection paths) => + source.Draw(options, new Pen(brush, thickness), paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + IPathCollection paths) => + source.Draw(new Pen(brush, thickness), paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + IPathCollection paths) => + source.Draw(options, new SolidBrush(color), thickness, paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + IPathCollection paths) => + source.Draw(new SolidBrush(color), thickness, paths); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs index 4dbe942f2b..f231f1baae 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs @@ -15,80 +15,80 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) + => source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. + /// The image this method extends. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) + => source.Draw(GraphicsOptions.Default, pen, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) + + => source.Draw(options, new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) + + => source.Draw(new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, Color color, float thickness, IPath path) + + => source.Draw(options, new SolidBrush(color), thickness, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, Color color, float thickness, IPath path) + + => source.Draw(new SolidBrush(color), thickness, path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs index 4dcfe00aa3..324e05e87b 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawPolygon(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawPolygon(new SolidBrush(color), thickness, points); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawPolygon(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawPolygon(options, new SolidBrush(color), thickness, points); /// /// Draws the provided Points as a closed Linear Polygon with the provided Pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(GraphicsOptions.Default, pen, new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided Pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, pen, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Polygon(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs index 918fb1e738..d0a6c8ccd2 100644 --- a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs @@ -15,80 +15,90 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the rectangle with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + RectangleF shape) => + source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Draws the outline of the rectangle with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, shape); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, RectangleF shape) => + source.Draw(GraphicsOptions.Default, pen, shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + RectangleF shape) => + source.Draw(options, new Pen(brush, thickness), shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + RectangleF shape) => + source.Draw(new Pen(brush, thickness), shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + RectangleF shape) => + source.Draw(options, new SolidBrush(color), thickness, shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + RectangleF shape) => + source.Draw(new SolidBrush(color), thickness, shape); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs index 46061ce9bc..163a676bbe 100644 --- a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs @@ -16,7 +16,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -25,14 +24,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, TPixel color, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, color, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + Color color, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, color, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -42,14 +44,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, TPixel color, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, Brushes.Solid(color), null, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + Color color, + PointF location) => + source.DrawText(options, text, font, Brushes.Solid(color), null, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -58,14 +64,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IBrush brush, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, brush, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IBrush brush, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, brush, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -75,14 +84,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IBrush brush, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, brush, null, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IBrush brush, + PointF location) => + source.DrawText(options, text, font, brush, null, location); /// /// Draws the text onto the the image outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -91,14 +104,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IPen pen, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, pen, location); /// /// Draws the text onto the the image outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -108,14 +124,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, null, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IPen pen, + PointF location) => + source.DrawText(options, text, font, null, pen, location); /// /// Draws the text onto the the image filled via the brush then outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -125,14 +145,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IBrush brush, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, brush, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IBrush brush, + IPen pen, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, brush, pen, location); /// /// Draws the text using the default resolution of 72dpi onto the the image filled via the brush then outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -143,8 +167,14 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawTextProcessor(options, text, font, brush, pen, location)); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IBrush brush, + IPen pen, + PointF location) => + source.ApplyProcessor(new DrawTextProcessor(options, text, font, brush, pen, location)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs index 64901c8e80..4a8ce44dbb 100644 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs @@ -14,9 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// a point on the longest extension of the ellipse and /// the ratio between longest and shortest extension. /// - /// The Pixel format that is used. - public sealed class EllipticGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class EllipticGradientBrush : GradientBrushBase { private readonly PointF center; @@ -24,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float axisRatio; - /// + /// /// The center of the elliptical gradient and 0 for the color stops. /// The end point of the reference axis of the ellipse. /// @@ -39,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing PointF referenceAxisEnd, float axisRatio, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.center = center; @@ -47,12 +45,12 @@ namespace SixLabors.ImageSharp.Processing this.axisRatio = axisRatio; } - /// - public override BrushApplicator CreateApplicator( + /// + public override BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, GraphicsOptions options) => - new RadialGradientBrushApplicator( + new RadialGradientBrushApplicator( source, options, this.center, @@ -62,7 +60,8 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF center; @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float referenceRadiusSquared; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image /// The options @@ -102,7 +101,7 @@ namespace SixLabors.ImageSharp.Processing PointF center, PointF referenceAxisEnd, float axisRatio, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options, colorStops, repetitionMode) { diff --git a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs index ff4de3ff8f..ca7eab93f9 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs @@ -15,14 +15,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Action path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + Action path) { var pb = new PathBuilder(); path(pb); @@ -33,38 +35,42 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Action path) - where TPixel : struct, IPixel - => source.Fill(GraphicsOptions.Default, brush, path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + IBrush brush, + Action path) => + source.Fill(GraphicsOptions.Default, brush, path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, Action path) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + Action path) => + source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, Action path) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + Color color, + Action path) => + source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs index da2dd35b6a..d750ff455b 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs @@ -14,14 +14,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The graphics options. /// The brush. /// The shapes. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPathCollection paths) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + IPathCollection paths) { foreach (IPath s in paths) { @@ -34,38 +36,42 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(GraphicsOptions.Default, brush, paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + IBrush brush, + IPathCollection paths) => + source.Fill(GraphicsOptions.Default, brush, paths); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + IPathCollection paths) => + source.Fill(options, new SolidBrush(color), paths); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + Color color, + IPathCollection paths) => + source.Fill(new SolidBrush(color), paths); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs index da10621113..7cf67612a2 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs @@ -15,51 +15,51 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) + => source.Fill(options, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) + => source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, IPath path) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, IPath path) + + => source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, IPath path) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) + + => source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs index 970ca22644..8150c7381e 100644 --- a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs @@ -15,51 +15,57 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(options, brush, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + params PointF[] points) => + source.Fill(options, brush, new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The brush. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, IBrush brush, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(brush, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + IBrush brush, + params PointF[] points) => + source.Fill(brush, new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, GraphicsOptions options, TPixel color, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + params PointF[] points) => + source.Fill(options, new SolidBrush(color), new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The color. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, TPixel color, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + Color color, + params PointF[] points) => + source.Fill(new SolidBrush(color), new Polygon(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs index 26bf214f71..ad512015e2 100644 --- a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs @@ -15,51 +15,53 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + RectangleF shape) => + source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext + Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape) => + source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), shape); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + RectangleF shape) => + source.Fill(options, new SolidBrush(color), shape); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), shape); + public static IImageProcessingContext + Fill(this IImageProcessingContext source, Color color, RectangleF shape) => + source.Fill(new SolidBrush(color), shape); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs index e566d03231..457ad98b0c 100644 --- a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs @@ -15,85 +15,85 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) + => source.Fill(GraphicsOptions.Default, brush); /// /// Flood fills the image with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) + + => source.Fill(new SolidBrush(color)); /// /// Flood fills the image with in the region with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) + => source.Fill(GraphicsOptions.Default, brush, region); /// /// Flood fills the image with in the region with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, Region region) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, Region region) + + => source.Fill(options, new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, Region region) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) + + => source.Fill(new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) + + => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); /// /// Flood fills the image with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FillProcessor(brush, options)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) + + => source.ApplyProcessor(new FillProcessor(brush, options)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs index 2dfae9e8f1..a877ea96cd 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs @@ -13,16 +13,14 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for Gradient brushes /// - /// The pixel format - public abstract class GradientBrushBase : IBrush - where TPixel : struct, IPixel + public abstract class GradientBrushBase : IBrush { - /// + /// /// Defines how the colors are repeated beyond the interval [0..1] /// The gradient colors. protected GradientBrushBase( GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) { this.RepetitionMode = repetitionMode; this.ColorStops = colorStops; @@ -36,25 +34,27 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the list of color stops for this gradient. /// - protected ColorStop[] ColorStops { get; } + protected ColorStop[] ColorStops { get; } - /// - public abstract BrushApplicator CreateApplicator( + /// + public abstract BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, - GraphicsOptions options); + GraphicsOptions options) + where TPixel : struct, IPixel; /// /// Base class for gradient brush applicators /// - protected abstract class GradientBrushApplicatorBase : BrushApplicator + protected abstract class GradientBrushApplicatorBase : BrushApplicator + where TPixel : struct, IPixel { - private readonly ColorStop[] colorStops; + private readonly ColorStop[] colorStops; private readonly GradientRepetitionMode repetitionMode; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target. /// The options. @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing protected GradientBrushApplicatorBase( ImageFrame target, GraphicsOptions options, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options) { @@ -111,11 +111,11 @@ namespace SixLabors.ImageSharp.Processing throw new ArgumentOutOfRangeException(); } - (ColorStop from, ColorStop to) = this.GetGradientSegment(positionOnCompleteGradient); + (ColorStop from, ColorStop to) = this.GetGradientSegment(positionOnCompleteGradient); if (from.Color.Equals(to.Color)) { - return from.Color; + return from.Color.ToPixel(); } else { @@ -150,14 +150,14 @@ namespace SixLabors.ImageSharp.Processing /// protected abstract float PositionOnGradient(float x, float y); - private (ColorStop from, ColorStop to) GetGradientSegment( + private (ColorStop from, ColorStop to) GetGradientSegment( float positionOnCompleteGradient) { - ColorStop localGradientFrom = this.colorStops[0]; - ColorStop localGradientTo = default; + ColorStop localGradientFrom = this.colorStops[0]; + ColorStop localGradientTo = default; // TODO: ensure colorStops has at least 2 items (technically 1 would be okay, but that's no gradient) - foreach (ColorStop colorStop in this.colorStops) + foreach (ColorStop colorStop in this.colorStops) { localGradientTo = colorStop; diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs index efdc852f28..1a6f8d79ab 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs @@ -14,15 +14,15 @@ namespace SixLabors.ImageSharp.Processing /// - a set of colors in relative distances to each other. /// /// The pixel format - public sealed class LinearGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class LinearGradientBrush : GradientBrushBase + { private readonly PointF p1; private readonly PointF p2; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Start point /// End point @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing PointF p1, PointF p2, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.p1 = p1; @@ -40,13 +40,14 @@ namespace SixLabors.ImageSharp.Processing } /// - public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); + public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); /// /// The linear gradient brush applicator. /// - private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF start; @@ -83,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float length; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source /// start point of the gradient @@ -95,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing ImageFrame source, PointF start, PointF end, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode, GraphicsOptions options) : base(source, options, colorStops, repetitionMode) diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 0e66756721..21690055e1 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -34,7 +34,6 @@ namespace SixLabors.ImageSharp.Processing /// 0 /// /// - /// The pixel format. public class PatternBrush : IBrush { /// @@ -44,7 +43,7 @@ namespace SixLabors.ImageSharp.Processing private readonly DenseMatrix patternVector; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the fore. /// Color of the back. @@ -55,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the fore. /// Color of the back. @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing /// Initializes a new instance of the class. /// /// The brush. - internal PatternBrush(PatternBrush brush) + internal PatternBrush(PatternBrush brush) { this.pattern = brush.pattern; this.patternVector = brush.patternVector; diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs index d33d099931..84a97e7d1f 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs @@ -11,15 +11,14 @@ namespace SixLabors.ImageSharp.Processing /// /// A Circular Gradient Brush, defined by center point and radius. /// - /// The pixel format. - public sealed class RadialGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class RadialGradientBrush : GradientBrushBase + { private readonly PointF center; private readonly float radius; - /// + /// /// The center of the circular gradient and 0 for the color stops. /// The radius of the circular gradient and 1 for the color stops. /// Defines how the colors in the gradient are repeated. @@ -28,19 +27,19 @@ namespace SixLabors.ImageSharp.Processing PointF center, float radius, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.center = center; this.radius = radius; } - /// - public override BrushApplicator CreateApplicator( + /// + public override BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, GraphicsOptions options) => - new RadialGradientBrushApplicator( + new RadialGradientBrushApplicator( source, options, this.center, @@ -49,14 +48,15 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF center; private readonly float radius; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image /// The options. @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Processing GraphicsOptions options, PointF center, float radius, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options, colorStops, repetitionMode) { diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 537418de24..4d5bf6d513 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -141,7 +141,6 @@ namespace SixLabors.ImageSharp /// /// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings. /// - /// The pixel format /// the color /// true if the color can be considered opaque /// From 8271ef18c9225e7ece42561413accf10d63dc09c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:52:33 +0200 Subject: [PATCH 13/27] everything builds --- .../Drawing/DrawBeziers.cs | 2 +- .../Drawing/DrawLines.cs | 2 +- .../Drawing/DrawPolygon.cs | 2 +- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 4 +- .../Drawing/DrawTextOutline.cs | 23 +++- .../Drawing/DrawBezierTests.cs | 2 +- .../Drawing/DrawComplexPolygonTests.cs | 2 +- .../Drawing/DrawLinesTests.cs | 12 +- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 4 +- .../Drawing/DrawPolygonTests.cs | 2 +- .../Drawing/FillComplexPolygonTests.cs | 2 +- .../Drawing/FillEllipticGradientBrushTest.cs | 36 +++--- .../Drawing/FillLinearGradientBrushTests.cs | 104 +++++++++--------- .../Drawing/FillPatternBrushTests.cs | 2 +- .../Drawing/FillPolygonTests.cs | 12 +- .../Drawing/FillRadialGradientBrushTests.cs | 14 +-- .../Drawing/FillRegionProcessorTests.cs | 11 +- .../Drawing/FillSolidBrushTests.cs | 22 ++-- .../Drawing/Paths/DrawPathCollection.cs | 16 +-- .../Drawing/Paths/FillPath.cs | 16 +-- .../Drawing/Paths/FillPathCollection.cs | 16 +-- .../Drawing/Paths/FillPolygon.cs | 16 +-- .../Drawing/Paths/FillRectangle.cs | 16 +-- .../Drawing/RecolorImageTests.cs | 4 +- .../Drawing/SolidBezierTests.cs | 2 +- .../Drawing/SolidFillBlendedShapesTests.cs | 26 ++--- .../ImageSharp.Tests/Drawing/Text/DrawText.cs | 70 ++++++------ .../Drawing/Text/DrawTextOnImageTests.cs | 12 +- tests/ImageSharp.Tests/Issues/Issue412.cs | 6 +- .../ImageProviders/SolidProvider.cs | 3 +- .../TestUtilities/TestImageExtensions.cs | 14 +++ 31 files changed, 248 insertions(+), 227 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs index 0a343864d8..8999afaeda 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawBeziers(pen, new[] { new PointF(10, 500), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs index 00942cc364..408e87f9ee 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawLines(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs index dcaf4bae60..2b4cff8cbe 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawPolygon(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 8c840d8c31..28f410e7d1 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); + image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); } } @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Benchmarks image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) + IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) where TPixel : struct, IPixel { float dpiX = 72; diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index ee17adbb55..658590e2d4 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) using (var font = new Font("Arial", 12, GraphicsUnit.Point)) using (var gp = new GraphicsPath()) { @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); + image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); } } @@ -53,10 +53,25 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10))); + image.Mutate( + x => DrawTextOldVersion( + x, + new TextGraphicsOptions(true) { WrapTextWidth = 780 }, + TextToRender, + font, + null, + Processing.Pens.Solid(Rgba32.HotPink, 10), + new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, + TextGraphicsOptions options, + string text, + SixLabors.Fonts.Font font, + IBrush brush, + IPen pen, + SixLabors.Primitives.PointF location) where TPixel : struct, IPixel { var style = new SixLabors.Fonts.RendererOptions(font, options.DpiX, options.DpiY, location) diff --git a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index 0f29728c9f..4ccc7fd355 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - provider.RunValidatingProcessorTest( x => x.DrawBeziers(color.ToPixel(), 5f, points), + provider.RunValidatingProcessorTest( x => x.DrawBeziers(color, 5f, points), testDetails, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); diff --git a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs index b6e105a199..f28f3345fc 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing testDetails += "_Dashed"; } - Pen pen = dashed ? Pens.Dash(color.ToPixel(), 5f) : Pens.Solid(color.ToPixel(), 5f); + Pen pen = dashed ? Pens.Dash(color, 5f) : Pens.Solid(color, 5f); provider.RunValidatingProcessorTest( x => x.Draw(pen, clipped), diff --git a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs index c225b921e6..12eb150b1b 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = new Pen(color.ToPixel(), thickness); + Pen pen = new Pen(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dash(color.ToPixel(), thickness); + Pen pen = Pens.Dash(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dot(color.ToPixel(), thickness); + Pen pen = Pens.Dot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDot(color.ToPixel(), thickness); + Pen pen = Pens.DashDot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDotDot(color.ToPixel(), thickness); + Pen pen = Pens.DashDotDot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing float alpha, float thickness, bool antialias, - Pen pen) + Pen pen) where TPixel : struct, IPixel { SixLabors.Primitives.PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index c638107b81..5e9743c31a 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; provider.RunValidatingProcessorTest( - x => x.Draw(color.ToPixel(), thickness, path), + x => x.Draw(color, thickness, path), testDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = Color.White; - Pen pen = Pens.Solid(color.ToPixel(), 5f); + Pen pen = Pens.Solid(color, 5f); provider.RunValidatingProcessorTest( x => diff --git a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs index 8a0f256670..b7c54fdbd1 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; provider.RunValidatingProcessorTest( - c => c.DrawPolygon(options, color.ToPixel(), thickness, simplePath), + c => c.DrawPolygon(options, color, thickness, simplePath), outputDetails, appendSourceFileOrDescription: false); } diff --git a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs index 3887cb9a7a..d6c85cd1d6 100644 --- a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } provider.RunValidatingProcessorTest( - x => x.Fill(color.ToPixel(), clipped), + x => x.Fill(color, clipped), testDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); diff --git a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs index fa4d4a709f..c61f770c9f 100644 --- a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs +++ b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs @@ -23,18 +23,18 @@ namespace SixLabors.ImageSharp.Tests.Drawing TestImageProvider provider) where TPixel : struct, IPixel { - TPixel red = NamedColors.Red; + Color red = Color.Red; using (Image image = provider.GetImage()) { var unicolorLinearGradientBrush = - new EllipticGradientBrush( + new EllipticGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), 1.0f, GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -58,22 +58,22 @@ namespace SixLabors.ImageSharp.Tests.Drawing float ratio) where TPixel : struct, IPixel { - TPixel yellow = NamedColors.Yellow; - TPixel red = NamedColors.Red; - TPixel black = NamedColors.Black; + Color yellow = Color.Yellow; + Color red = Color.Red; + Color black = Color.Black; provider.VerifyOperation( TolerantComparer, image => { - var unicolorLinearGradientBrush = new EllipticGradientBrush( + var unicolorLinearGradientBrush = new EllipticGradientBrush( new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2), new SixLabors.Primitives.Point(image.Width / 2, (image.Width * 2) / 3), ratio, GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -114,9 +114,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel yellow = NamedColors.Yellow; - TPixel red = NamedColors.Red; - TPixel black = NamedColors.Black; + Color yellow = Color.Yellow; + Color red = Color.Red; + Color black = Color.Black; var center = new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2); @@ -128,14 +128,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing int axisX = center.X + (int)-(offsetY * sin); int axisY = center.Y + (int)(offsetY * cos); - var unicolorLinearGradientBrush = new EllipticGradientBrush( + var unicolorLinearGradientBrush = new EllipticGradientBrush( center, new SixLabors.Primitives.Point(axisX, axisY), ratio, GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 0f4a98a24a..5d1442e79c 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -29,14 +29,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel red = NamedColors.Red; + Color red = Color.Red; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -58,12 +58,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, - new ColorStop(0, NamedColors.Blue), - new ColorStop(1, NamedColors.Yellow)); + new ColorStop(0, Color.Blue), + new ColorStop(1, Color.Yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -79,15 +79,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -109,15 +109,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width / 10, 0), repetitionMode, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -140,26 +140,26 @@ namespace SixLabors.ImageSharp.Tests.Drawing // ensure the input data is valid Assert.True(pattern.Length > 0); - TPixel black = NamedColors.Black; - TPixel white = NamedColors.White; + Color black = Color.Black; + Color white = Color.White; // create the input pattern: 0, followed by each of the arguments twice, followed by 1.0 - toggling black and white. - ColorStop[] colorStops = - Enumerable.Repeat(new ColorStop(0, black), 1) + ColorStop[] colorStops = + Enumerable.Repeat(new ColorStop(0, black), 1) .Concat( pattern .SelectMany((f, index) => new[] { - new ColorStop(f, index % 2 == 0 ? black : white), - new ColorStop(f, index % 2 == 0 ? white : black) + new ColorStop(f, index % 2 == 0 ? black : white), + new ColorStop(f, index % 2 == 0 ? white : black) })) - .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) + .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) .ToArray(); using (Image image = provider.GetImage()) { var unicolorLinearGradientBrush = - new LinearGradientBrush( + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, @@ -196,15 +196,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(0, image.Height), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -254,16 +254,16 @@ namespace SixLabors.ImageSharp.Tests.Drawing int endX = image.Height - startX - 1; int endY = image.Width - startY - 1; - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; var unicolorLinearGradientBrush = - new LinearGradientBrush( + new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); image.DebugSave( @@ -310,22 +310,21 @@ namespace SixLabors.ImageSharp.Tests.Drawing int[] stopColorCodes) where TPixel : struct, IPixel { - TPixel[] colors = + Color[] colors = { - NamedColors.Navy, NamedColors.LightGreen, NamedColors.Yellow, - NamedColors.Red + Color.Navy, Color.LightGreen, Color.Yellow, + Color.Red }; var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; + var colorStops = new ColorStop[stopPositions.Length]; for (int i = 0; i < stopPositions.Length; i++) { - TPixel color = colors[stopColorCodes[i % colors.Length]]; + Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = default; - color.ToRgba32(ref rgba); + colorStops[i] = new ColorStop(position, color); + Rgba32 rgba = color; coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); } @@ -334,7 +333,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, @@ -357,22 +356,21 @@ namespace SixLabors.ImageSharp.Tests.Drawing int[] stopColorCodes) where TPixel : struct, IPixel { - TPixel[] colors = + Color[] colors = { - NamedColors.Black, NamedColors.Blue, NamedColors.Red, - NamedColors.White, NamedColors.Lime + Color.Black, Color.Blue, Color.Red, + Color.White, Color.Lime }; var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; + var colorStops = new ColorStop[stopPositions.Length]; for (int i = 0; i < stopPositions.Length; i++) { - TPixel color = colors[stopColorCodes[i % colors.Length]]; + Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = default; - color.ToRgba32(ref rgba); + colorStops[i] = new ColorStop(position, color); + Rgba32 rgba = color; coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); } @@ -381,7 +379,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs index dcc689fe1c..647f285103 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { public class FillPatternBrushTests { - private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) + private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); using (var image = new Image(20, 20)) diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs index 43029e6957..f84d2b31c9 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString outputDetails = $"{colorName}_A{alpha}{aa}"; provider.RunValidatingProcessorTest( - c => c.FillPolygon(options, color.ToPixel(), simplePath), + c => c.FillPolygon(options, color, simplePath), outputDetails, appendSourceFileOrDescription: false); } @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.LightGreen; provider.RunValidatingProcessorTest( - c => c.FillPolygon(color.ToPixel(), points), + c => c.FillPolygon(color, points), appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing }; Color color = Color.Yellow; - var brush = Brushes.Horizontal(color.ToPixel()); + var brush = Brushes.Horizontal(color); provider.RunValidatingProcessorTest( c => c.FillPolygon(brush, simplePath), @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.White; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), appendSourceFileOrDescription: false); } @@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testOutput = $"V({vertices})_R({radius})_Ang({angleDeg})"; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), testOutput, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.Azure; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs index 7461347de1..818340dd22 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs @@ -21,15 +21,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel red = NamedColors.Red; + Color red = Color.Red; var unicolorRadialGradientBrush = - new RadialGradientBrush( + new RadialGradientBrush( new SixLabors.Primitives.Point(0, 0), 100, GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorRadialGradientBrush)); @@ -56,12 +56,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - var brush = new RadialGradientBrush( + var brush = new RadialGradientBrush( new SixLabors.Primitives.Point(centerX, centerY), image.Width / 2f, GradientRepetitionMode.None, - new ColorStop(0, NamedColors.Red), - new ColorStop(1, NamedColors.Yellow)); + new ColorStop(0, Color.Red), + new ColorStop(1, Color.Yellow)); image.Mutate(x => x.Fill(brush)); }, diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index dc7da35433..bb78054a4d 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -8,6 +8,7 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using Xunit; using SixLabors.ImageSharp.Processing.Processors.Drawing; @@ -30,14 +31,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing { var bounds = new Rectangle(0, 0, 1, 1); - var brush = new Mock>(); + var brush = new Mock(); var region = new MockRegion2(bounds); var options = new GraphicsOptions(antialias) { AntialiasSubpixelDepth = 1 }; - var processor = new FillRegionProcessor(brush.Object, region, options); + var processor = new FillRegionProcessor(brush.Object, region, options); var img = new Image(1, 1); processor.Apply(img, bounds); @@ -48,9 +49,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing public void FillOffCanvas() { var bounds = new Rectangle(-100, -10, 10, 10); - var brush = new Mock>(); + var brush = new Mock(); var options = new GraphicsOptions(true); - var processor = new FillRegionProcessor(brush.Object, new MockRegion1(), options); + var processor = new FillRegionProcessor(brush.Object, new MockRegion1(), options); var img = new Image(10, 10); processor.Apply(img, bounds); } @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var img = new Image(10, 10)) { - img.Mutate(x => x.DrawLines(new Pen(Rgba32.Black, 10), new SixLabors.Primitives.PointF[] { + img.Mutate(x => x.DrawLines(new Pen(Rgba32.Black, 10), new SixLabors.Primitives.PointF[] { new Vector2(-10, 5), new Vector2(20, 5), })); diff --git a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs index 639b3fe81a..358552bf81 100644 --- a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = NamedColors.HotPink; + Color color = Color.HotPink; image.Mutate(c => c.Fill(color)); image.DebugSave(provider, appendPixelTypeToFileName: false); @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = NamedColors.HotPink; + Color color = Color.HotPink; image.Mutate(c => c.Fill(color)); image.DebugSave(provider, appendSourceFileOrDescription: false); @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = TestUtils.GetPixelOfNamedColor(newColorName); + Color color = TestUtils.GetColorByName(newColorName); image.Mutate(c => c.Fill(color)); image.DebugSave( @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; var region = new RectangleF(x0, y0, w, h); - TPixel color = TestUtils.GetPixelOfNamedColor("Blue"); + Color color = TestUtils.GetColorByName("Blue"); provider.RunValidatingProcessorTest(c => c.Fill(color, region), testDetails, ImageComparer.Exact); } @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; var region = new RectangleF(x0, y0, w, h); - TPixel color = TestUtils.GetPixelOfNamedColor("Blue"); + Color color = TestUtils.GetColorByName("Blue"); provider.RunValidatingProcessorTestOnWrappedMemoryImage( c => c.Fill(color, region), @@ -150,11 +150,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing float blendPercentage) where TPixel : struct, IPixel { - var vec = TestUtils.GetPixelOfNamedColor(newColorName).ToVector4(); - vec.W = alpha; - - TPixel fillColor = default; - fillColor.FromVector4(vec); + Color fillColor = TestUtils.GetColorByName(newColorName).WithAlpha(alpha); using (Image image = provider.GetImage()) { @@ -169,11 +165,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing { var region = new ShapeRegion(new RectangularPolygon(0, 0, 16, 16)); - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor), region)); + image.Mutate(c => c.Fill(options, new SolidBrush(fillColor), region)); } else { - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); + image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); } var testOutputDetails = new @@ -194,7 +190,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing PixelBlender blender = PixelOperations.Instance.GetPixelBlender( blenderMode, PixelAlphaCompositionMode.SrcOver); - TPixel expectedPixel = blender.Blend(bgColor, fillColor, blendPercentage); + TPixel expectedPixel = blender.Blend(bgColor, fillColor.ToPixel(), blendPercentage); image.ComparePixelBufferTo(expectedPixel); } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs index 326517a4e1..5ab7894355 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class DrawPathCollection : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - Pen pen = Pens.Solid(Rgba32.HotPink, 1); + Color color = Color.HotPink; + Pen pen = Pens.Solid(Rgba32.HotPink, 1); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -81,14 +81,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); ShapePath region = Assert.IsType(processor.Region); ComplexPolygon polygon = Assert.IsType(region.Shape); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } @@ -100,14 +100,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); ShapePath region = Assert.IsType(processor.Region); ComplexPolygon polygon = Assert.IsType(region.Shape); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs index e72fbbdf24..d65dcd8c64 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPath : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushAndPath() { this.operations.Fill(this.brush, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushPathOptions() { this.operations.Fill(this.noneDefault, this.brush, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndPath() { this.operations.Fill(this.color, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorPathAndOptions() { this.operations.Fill(this.noneDefault, this.color, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs index ec7a5a20c8..1f8e2d423d 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPathCollection : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } @@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs index d8927a4683..b270a03cfc 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPolygon : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.PointF[] path = { new Vector2(10,10), new Vector2(20,10), @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { this.operations.FillPolygon(this.brush, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushPathAndOptions() { this.operations.FillPolygon(this.noneDefault, this.brush, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndPath() { this.operations.FillPolygon(this.color, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segemnt = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorPathAndOptions() { this.operations.FillPolygon(this.noneDefault, this.color, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segemnt = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs index 8f648e425f..6cb052aa8f 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs @@ -12,15 +12,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillRectangle : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.Rectangle rectangle = new SixLabors.Primitives.Rectangle(10, 10, 77, 76); [Fact] public void CorrectlySetsBrushAndRectangle() { this.operations.Fill(this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushRectangleAndOptions() { this.operations.Fill(this.noneDefault, this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndRectangle() { this.operations.Fill(this.color, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.Equal(rect.Size.Width, this.rectangle.Width); Assert.Equal(rect.Size.Height, this.rectangle.Height); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorRectangleAndOptions() { this.operations.Fill(this.noneDefault, this.color, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.Equal(rect.Size.Width, this.rectangle.Width); Assert.Equal(rect.Size.Height, this.rectangle.Height); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs index 461ca700f7..fae0bf72b4 100644 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { Color sourceColor = TestUtils.GetColorByName(sourceColorName); Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + var brush = new RecolorBrush(sourceColor, targetColor, threshold); FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; provider.RunValidatingProcessorTest(x => x.Fill(brush), testInfo); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { Color sourceColor = TestUtils.GetColorByName(sourceColorName); Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + var brush = new RecolorBrush(sourceColor, targetColor, threshold); FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; provider.RunValidatingProcessorTest(x => diff --git a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs index e8f53de010..fd8713cccd 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image image = provider.GetImage()) { image.Mutate(x => x.BackgroundColor(blue)); - image.Mutate(x => x.Fill(hotPink.ToPixel(), new Polygon(new CubicBezierLineSegment(simplePath)))); + image.Mutate(x => x.Fill(hotPink, new Polygon(new CubicBezierLineSegment(simplePath)))); image.DebugSave(provider); image.CompareToReferenceOutput(provider); } diff --git a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs index 94e12f8581..c34d50297a 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs @@ -43,11 +43,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = img.Height / 100; img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) ) .Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) ); @@ -69,17 +69,17 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = img.Height / 100; img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.Transparent, + Color.Transparent, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) ); @@ -101,22 +101,20 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = (img.Height / 100); img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); - var c = NamedColors.Red.ToVector4(); - c.W *= 0.5f; - var pixel = default(TPixel); - pixel.FromVector4(c); + + var transparentRed = Color.Red.WithAlpha(0.5f); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - pixel, + transparentRed, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) ); @@ -139,12 +137,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing dstImg.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); srcImg.Mutate( x => x.Fill( - NamedColors.Black, + Color.Black, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); dstImg.Mutate( diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs index 76f40e0aca..8520a2f3fb 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs @@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text { public class DrawText : BaseImageOperationsExtensionTest { - Rgba32 color = Rgba32.HotPink; + Rgba32 color = Color.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + SolidBrush brush = Brushes.Solid(Color.HotPink); IPath path = new SixLabors.Shapes.Path( new LinearLineSegment( @@ -39,57 +39,57 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text new TextGraphicsOptions(true), "123", this.Font, - Brushes.Solid(Rgba32.Red), + Brushes.Solid(Color.Red), null, Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSetAndNotPenDefaultOptions() { - this.operations.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), null, Vector2.Zero); + this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), null, Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Brushes.Solid(Rgba32.Red), Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), Vector2.Zero); + this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenColorSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Rgba32.Red, Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Color.Red, Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); - SolidBrush brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] public void FillsForEachACharachterWhenColorSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Rgba32.Red, Vector2.Zero); + this.operations.DrawText("123", this.Font, Color.Red, Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); - SolidBrush brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] @@ -100,39 +100,39 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text "123", this.Font, null, - Pens.Dash(Rgba32.Red, 1), + Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSetAndNotBrushDefaultOptions() { - this.operations.DrawText("123", this.Font, null, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText("123", this.Font, null, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText("123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); Assert.Equal("123", processor.Text); Assert.Equal(this.Font, processor.Font); - var penBrush = Assert.IsType>(processor.Pen.StrokeFill); - Assert.Equal(Rgba32.Red, penBrush.Color); + var penBrush = Assert.IsType(processor.Pen.StrokeFill); + Assert.Equal(Color.Red, penBrush.Color); Assert.Equal(1, processor.Pen.StrokeWidth); Assert.Equal(PointF.Empty, processor.Location); } @@ -144,19 +144,19 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text new TextGraphicsOptions(true), "123", this.Font, - Brushes.Solid(Rgba32.Red), - Pens.Dash(Rgba32.Red, 1), + Brushes.Solid(Color.Red), + Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); Assert.Equal("123", processor.Text); Assert.Equal(this.Font, processor.Font); - var brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + var brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); Assert.Equal(PointF.Empty, processor.Location); - var penBrush = Assert.IsType>(processor.Pen.StrokeFill); - Assert.Equal(Rgba32.Red, penBrush.Color); + var penBrush = Assert.IsType(processor.Pen.StrokeFill); + Assert.Equal(Color.Red, penBrush.Color); Assert.Equal(1, processor.Pen.StrokeWidth); } } diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 20ccb25a54..ebd9cf6448 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont("OpenSans-Regular.ttf", 36); - TPixel color = NamedColors.Black; + Color color = Color.Black; float padding = 5; var text = "A short piece of text"; @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( TextDrawingComparer, @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text HorizontalAlignment = HorizontalAlignment.Left, }; - TPixel color = NamedColors.Black; + Color color = Color.Black; // Based on the reported 0.0270% difference with AccuracyMultiple = 8 // We should avoid quality regressions leading to higher difference! @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( OutlinedTextDrawingComparer, @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( OutlinedTextDrawingComparer, @@ -217,7 +217,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text var comparer = ImageComparer.TolerantPercentage(0.2f); provider.RunValidatingProcessorTest( - x => x.DrawText(textOptions, text, font, NamedColors.Black, new PointF(10, 50)), + x => x.DrawText(textOptions, text, font, Color.Black, new PointF(10, 50)), details, comparer, appendPixelTypeToFileName: false, diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs index b0374ce1fa..f22d3a85cf 100644 --- a/tests/ImageSharp.Tests/Issues/Issue412.cs +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Issues { context.DrawLines( new GraphicsOptions(false), - NamedColors.Black, + Color.Black, 1, new[] { @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Tests.Issues context.DrawLines( new GraphicsOptions(false), - NamedColors.Red, + Color.Red, 1, new[] { @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Issues 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}]"); + Assert.True(Color.Red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs index 1ff95f60d0..88b30ce34e 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -53,8 +53,7 @@ namespace SixLabors.ImageSharp.Tests public override Image GetImage() { Image image = base.GetImage(); - TPixel color = default(TPixel); - color.FromRgba32(new Rgba32(this.r, this.g, this.b, this.a)); + Color color = new Rgba32(this.r, this.g, this.b, this.a); image.Mutate(x => x.Fill(color)); return image; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index c5aa1fb944..048c6347cd 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -484,6 +484,20 @@ namespace SixLabors.ImageSharp.Tests return image; } + + /// + /// All pixels in all frames should be exactly equal to 'expectedPixelColor.ToPixel()'. + /// + public static Image ComparePixelBufferTo(this Image image, Color expectedPixelColor) + where TPixel : struct, IPixel + { + foreach (ImageFrame imageFrame in image.Frames) + { + imageFrame.ComparePixelBufferTo(expectedPixelColor.ToPixel()); + } + + return image; + } /// /// All pixels in the frame should be exactly equal to 'expectedPixel'. From f0b70b63efa1f2e09e388accc049aacfde05bd0c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:56:40 +0200 Subject: [PATCH 14/27] tests are passing --- .../Processing/Processors/Text/DrawTextProcessor.cs | 2 +- tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 016cf56dea..d1e28afeb8 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text public IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { - throw new NotImplementedException(); + return new DrawTextProcessor(this); } } diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 5d1442e79c..361e7e70d1 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -176,7 +176,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing // the result must be a black and white pattern, no other color should occur: Assert.All( Enumerable.Range(0, image.Width).Select(i => image[i, 0]), - color => Assert.True(color.Equals(black) || color.Equals(white))); + color => Assert.True( + color.Equals(black.ToPixel()) || color.Equals(white.ToPixel()))); image.CompareToReferenceOutput( TolerantComparer, From f7df30f58c45b53dbf73fc2f6b0fe8362854cf47 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:20:34 +0200 Subject: [PATCH 15/27] move drawing extensions to a (non-namespace-provider) subfolder --- .../ImageSharp.Drawing.csproj.DotSettings | 2 + .../{ => Extensions}/DrawBezierExtensions.cs | 0 .../{ => Extensions}/DrawImageExtensions.cs | 272 +++++++++--------- .../{ => Extensions}/DrawLineExtensions.cs | 0 .../DrawPathCollectionExtensions.cs | 0 .../{ => Extensions}/DrawPathExtensions.cs | 0 .../{ => Extensions}/DrawPolygonExtensions.cs | 0 .../DrawRectangleExtensions.cs | 0 .../{ => Extensions}/DrawTextExtensions.cs | 0 .../FillPathBuilderExtensions.cs | 0 .../FillPathCollectionExtensions.cs | 0 .../{ => Extensions}/FillPathExtensions.cs | 0 .../{ => Extensions}/FillPolygonExtensions.cs | 0 .../FillRectangleExtensions.cs | 0 .../{ => Extensions}/FillRegionExtensions.cs | 0 15 files changed, 138 insertions(+), 136 deletions(-) create mode 100644 src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawBezierExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawImageExtensions.cs (98%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawLineExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPathCollectionExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPathExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPolygonExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawRectangleExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawTextExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathBuilderExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathCollectionExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPolygonExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillRectangleExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillRegionExtensions.cs (100%) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings new file mode 100644 index 0000000000..a728b54979 --- /dev/null +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs similarity index 98% rename from src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs index a8ee4d90bc..58459ebc5d 100644 --- a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs @@ -1,137 +1,137 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of images to the type. - /// - public static class DrawImageExtensions - { - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The blending mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The color blending mode. - /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The options, including the blending type and blending amount. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The color blending to apply. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The color blending to apply. - /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The options containing the blend mode and opacity. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Drawing; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Adds extensions that allow the drawing of images to the type. + /// + public static class DrawImageExtensions + { + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The blending mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The color blending mode. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The options, including the blending type and blending amount. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The color blending to apply. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The color blending to apply. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs From c07bd2fd97bba0648a9f82806784094aced0fff1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:24:27 +0200 Subject: [PATCH 16/27] rename files --- .../Processing/{ColorStop{TPixel}.cs => ColorStop.cs} | 0 ...cGradientBrush{TPixel}.cs => EllipticGradientBrush.cs} | 0 ...{GradientBrushBase{TPixel}.cs => GradientBrushBase.cs} | 0 .../Processing/{ImageBrush{TPixel}.cs => ImageBrush.cs} | 7 +++---- ...earGradientBrush{TPixel}.cs => LinearGradientBrush.cs} | 1 - .../{PatternBrush{TPixel}.cs => PatternBrush.cs} | 0 .../Processing/{Pen{TPixel}.cs => Pen.cs} | 8 ++++---- ...ialGradientBrush{TPixel}.cs => RadialGradientBrush.cs} | 0 .../{RecolorBrush{TPixel}.cs => RecolorBrush.cs} | 1 - .../Processing/{SolidBrush{TPixel}.cs => SolidBrush.cs} | 0 tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs | 2 +- tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs | 2 +- 12 files changed, 9 insertions(+), 12 deletions(-) rename src/ImageSharp.Drawing/Processing/{ColorStop{TPixel}.cs => ColorStop.cs} (100%) rename src/ImageSharp.Drawing/Processing/{EllipticGradientBrush{TPixel}.cs => EllipticGradientBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{GradientBrushBase{TPixel}.cs => GradientBrushBase.cs} (100%) rename src/ImageSharp.Drawing/Processing/{ImageBrush{TPixel}.cs => ImageBrush.cs} (97%) rename src/ImageSharp.Drawing/Processing/{LinearGradientBrush{TPixel}.cs => LinearGradientBrush.cs} (98%) rename src/ImageSharp.Drawing/Processing/{PatternBrush{TPixel}.cs => PatternBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{Pen{TPixel}.cs => Pen.cs} (88%) rename src/ImageSharp.Drawing/Processing/{RadialGradientBrush{TPixel}.cs => RadialGradientBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{RecolorBrush{TPixel}.cs => RecolorBrush.cs} (99%) rename src/ImageSharp.Drawing/Processing/{SolidBrush{TPixel}.cs => SolidBrush.cs} (100%) diff --git a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ColorStop.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/ColorStop.cs diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/GradientBrushBase.cs diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs similarity index 97% rename from src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/ImageBrush.cs index d5ec1123d7..983c09adbf 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -14,8 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of an image brush for painting images within areas. /// - /// The pixel format. - public class ImageBrush : IBrush + public class ImageBrush : IBrush { /// /// The image to paint. @@ -23,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly Image image; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image. public ImageBrush(Image image) @@ -74,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing private readonly int offsetX; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image. /// The image. diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs similarity index 98% rename from src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index 1a6f8d79ab..fac43ad634 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -13,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing /// Supported right now: /// - a set of colors in relative distances to each other. /// - /// The pixel format public sealed class LinearGradientBrush : GradientBrushBase { diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/PatternBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Pen.cs similarity index 88% rename from src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/Pen.cs index 922394946a..c9d60a50e2 100644 --- a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Pen.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float[] pattern; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. /// The width. @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. /// The width. @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. /// The width. @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. /// The width. diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs similarity index 99% rename from src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/RecolorBrush.cs index ff098dce7c..fca95be327 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs @@ -15,7 +15,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of a brush that can recolor an image /// - /// The pixel format. public class RecolorBrush : IBrush { /// diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/SolidBrush.cs diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs index 772f62d5cc..e1fc7c30c1 100644 --- a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (var src = new Image(5, 5)) { - var brush = new ImageBrush(src); + var brush = new ImageBrush(src); using (var dest = new Image(10, 10)) { dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs index f84d2b31c9..5393e9954f 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) { - var brush = new ImageBrush(brushImage); + var brush = new ImageBrush(brushImage); provider.RunValidatingProcessorTest( c => c.FillPolygon(brush, simplePath), From efaa3c05ed5829f4a75937c27b84915712d29527 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:54:38 +0200 Subject: [PATCH 17/27] ImageBrush can apply a source image of a different pixel type than the target --- .../Processing/ImageBrush.cs | 44 ++++++++++++++----- src/ImageSharp/Image.cs | 17 +++++++ src/ImageSharp/Image{TPixel}.cs | 11 +---- .../Drawing/DrawImageTests.cs | 2 + .../Drawing/FillImageBrushTests.cs | 19 ++++++++ .../TestUtilities/ImagingTestCaseUtility.cs | 6 +-- .../TestUtilities/TestImageExtensions.cs | 29 +++++------- tests/Images/External | 2 +- 8 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index 983c09adbf..c2a8d3a261 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -37,8 +38,14 @@ namespace SixLabors.ImageSharp.Processing GraphicsOptions options) where TPixel : struct, IPixel { - Image specificImage = (Image)this.image; - return new ImageBrushApplicator(source, specificImage.Frames.RootFrame, region, options); + if (this.image is Image specificImage) + { + return new ImageBrushApplicator(source, specificImage, region, options, false); + } + + specificImage = this.image.CloneAs(); + + return new ImageBrushApplicator(source, specificImage, region, options, true); } /// @@ -47,10 +54,11 @@ namespace SixLabors.ImageSharp.Processing private class ImageBrushApplicator : BrushApplicator where TPixel : struct, IPixel { - /// - /// The source image. - /// - private readonly ImageFrame source; + private ImageFrame sourceFrame; + + private Image sourceImage; + + private readonly bool shouldDisposeImage; /// /// The y-length. @@ -79,10 +87,18 @@ namespace SixLabors.ImageSharp.Processing /// The image. /// The region. /// The options - public ImageBrushApplicator(ImageFrame target, ImageFrame image, RectangleF region, GraphicsOptions options) + /// Whether to dispose the image on disposal of the applicator. + public ImageBrushApplicator( + ImageFrame target, + Image image, + RectangleF region, + GraphicsOptions options, + bool shouldDisposeImage) : base(target, options) { - this.source = image; + this.sourceImage = image; + this.sourceFrame = image.Frames.RootFrame; + this.shouldDisposeImage = shouldDisposeImage; this.xLength = image.Width; this.yLength = image.Height; this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0); @@ -103,13 +119,19 @@ namespace SixLabors.ImageSharp.Processing { int srcX = (x - this.offsetX) % this.xLength; int srcY = (y - this.offsetY) % this.yLength; - return this.source[srcX, srcY]; + return this.sourceFrame[srcX, srcY]; } } /// public override void Dispose() { + if (this.shouldDisposeImage) + { + this.sourceImage?.Dispose(); + this.sourceImage = null; + this.sourceFrame = null; + } } /// @@ -124,7 +146,7 @@ namespace SixLabors.ImageSharp.Processing int sourceY = (y - this.offsetY) % this.yLength; int offsetX = x - this.offsetX; - Span sourceRow = this.source.GetPixelRowSpan(sourceY); + Span sourceRow = this.sourceFrame.GetPixelRowSpan(sourceY); for (int i = 0; i < scanline.Length; i++) { @@ -137,7 +159,7 @@ namespace SixLabors.ImageSharp.Processing Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); this.Blender.Blend( - this.source.Configuration, + this.sourceFrame.Configuration, destinationRow, destinationRow, overlaySpan, diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 1566fd0eed..db03281064 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -87,6 +87,23 @@ namespace SixLabors.ImageSharp EncodeVisitor visitor = new EncodeVisitor(encoder, stream); this.AcceptVisitor(visitor); } + + /// + /// Returns a copy of the image in the given pixel format. + /// + /// The pixel format. + /// The + public Image CloneAs() + where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); + + /// + /// Returns a copy of the image in the given pixel format. + /// + /// The pixel format. + /// The configuration providing initialization code which allows extending the library. + /// The . + public abstract Image CloneAs(Configuration configuration) + where TPixel2 : struct, IPixel; /// /// Accept a . diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 27e2bc593c..2b93b710b0 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -153,22 +153,13 @@ namespace SixLabors.ImageSharp return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } - /// - /// Returns a copy of the image in the given pixel format. - /// - /// The pixel format. - /// The - public Image CloneAs() - where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); - /// /// Returns a copy of the image in the given pixel format. /// /// The pixel format. /// The configuration providing initialization code which allows extending the library. /// The . - public Image CloneAs(Configuration configuration) - where TPixel2 : struct, IPixel + public override Image CloneAs(Configuration configuration) { IEnumerable> clonedFrames = this.Frames.Select(x => x.CloneAs(configuration)); return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 70879e6feb..e48a0b0ae3 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -175,5 +175,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } } + + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs index e1fc7c30c1..d33d7b70d2 100644 --- a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs @@ -32,5 +32,24 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } } + + [Theory] + [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] + public void UseBrushOfDifferentPixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + byte[] data = TestFile.Create(TestImages.Png.Ducky).Bytes; + using (Image background = provider.GetImage()) + using (Image overlay = provider.PixelType == PixelTypes.Rgba32 + ? (Image)Image.Load(data) + : Image.Load(data)) + { + var brush = new ImageBrush(overlay); + background.Mutate(c => c.Fill(brush)); + + background.DebugSave(provider, appendSourceFileOrDescription : false); + background.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs index c91ef56a1a..92cc9f6368 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -152,21 +152,19 @@ namespace SixLabors.ImageSharp.Tests /// /// Encodes image by the format matching the required extension, than saves it to the recommended output file. /// - /// The pixel format of the image /// The image instance /// The requested extension /// Optional encoder /// A value indicating whether to append the pixel type to the test output file name /// A boolean indicating whether to append to the test output file name. /// Additional information to append to the test output file name - public string SaveTestOutputFile( - Image image, + public string SaveTestOutputFile( + Image image, string extension = null, IImageEncoder encoder = null, object testOutputDetails = null, bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) - where TPixel : struct, IPixel { string path = this.GetTestOutputFileName( extension, diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 048c6347cd..e77b1974d3 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -55,17 +55,16 @@ namespace SixLabors.ImageSharp.Tests }); } - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, FormattableString testOutputDetails, string extension = "png", bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) - where TPixel : struct, IPixel { - return image.DebugSave( + image.DebugSave( provider, (object)testOutputDetails, extension, @@ -77,7 +76,6 @@ namespace SixLabors.ImageSharp.Tests /// /// Saves the image only when not running in the CI server. /// - /// The pixel format /// The image /// The image provider /// Details to be concatenated to the test output file, describing the parameters of the test. @@ -85,15 +83,14 @@ namespace SixLabors.ImageSharp.Tests /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. /// Custom encoder to use. - public static Image DebugSave( - this Image image, + public static Image DebugSave( + this Image image, ITestImageProvider provider, object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) - where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) { @@ -111,37 +108,34 @@ namespace SixLabors.ImageSharp.Tests return image; } - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, IImageEncoder encoder, FormattableString testOutputDetails, bool appendPixelTypeToFileName = true) - where TPixel : struct, IPixel { - return image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); + image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); } /// /// Saves the image only when not running in the CI server. /// - /// The pixel format /// The image /// The image provider /// The image encoder /// Details to be concatenated to the test output file, describing the parameters of the test. /// A boolean indicating whether to append the pixel type to the output file name. - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, IImageEncoder encoder, object testOutputDetails = null, bool appendPixelTypeToFileName = true) - where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) { - return image; + return; } // We are running locally then we want to save it out @@ -150,7 +144,6 @@ namespace SixLabors.ImageSharp.Tests encoder: encoder, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName); - return image; } public static Image DebugSaveMultiFrame( diff --git a/tests/Images/External b/tests/Images/External index 55c250ab80..9d1d9dd537 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 55c250ab80f7f9fc26208b9b9d9590cbe8012446 +Subproject commit 9d1d9dd53755007ee812907f64304d1925c6a91a From 0bd86ddcb698d59008d265db2f576ae345740d68 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 01:56:07 +0200 Subject: [PATCH 18/27] non-generic DrawImageProcessor --- .../Extensions/DrawImageExtensions.cs | 134 +++++++++++------- .../Processors/Drawing/DrawImageProcessor.cs | 117 ++++++++++++--- 2 files changed, 187 insertions(+), 64 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs index 58459ebc5d..981cf1bef4 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs @@ -15,98 +15,126 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + GraphicsOptions.Default.ColorBlendingMode, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The blending mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + PixelColorBlendingMode colorBlending, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + colorBlending, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The color blending mode. /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => + source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The options, including the blending type and blending amount. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + GraphicsOptions options) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + options.ColorBlendingMode, + options.AlphaCompositionMode, + options.BlendPercentage)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + GraphicsOptions.Default.ColorBlendingMode, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The color blending to apply. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + PixelColorBlendingMode colorBlending, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + colorBlending, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. @@ -114,24 +142,34 @@ namespace SixLabors.ImageSharp.Processing /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => + source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The options containing the blend mode and opacity. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + GraphicsOptions options) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + options.ColorBlendingMode, + options.AlphaCompositionMode, + options.BlendPercentage)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 6c03537eb3..0fbef9afea 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -13,14 +13,90 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + public class DrawImageProcessor : IImageProcessor + { + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) + { + this.Image = image; + this.Location = location; + this.ColorBlendingMode = colorBlendingMode; + this.AlphaCompositionMode = alphaCompositionMode; + this.Opacity = opacity; + } + + /// + /// Gets the image to blend + /// + public Image Image { get; } + + /// + /// Gets the location to draw the blended image + /// + public Point Location { get; } + + /// + /// Gets the blending mode to use when drawing the image. + /// + public PixelColorBlendingMode ColorBlendingMode { get; } + + /// + /// Gets the Alpha blending mode to use when drawing the image. + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; } + + /// + /// Gets the opacity of the image to blend + /// + public float Opacity { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixelBg : struct, IPixel + { + var visitor = new ProcessorFactoryVisitor(this); + this.Image.AcceptVisitor(visitor); + return visitor.Result; + } + + private class ProcessorFactoryVisitor : IImageVisitor + where TPixelBg : struct, IPixel + { + private readonly DrawImageProcessor definition; + + public ProcessorFactoryVisitor(DrawImageProcessor definition) + { + this.definition = definition; + } + + public IImageProcessor Result { get; private set; } + + public void Visit(Image image) + where TPixelFg : struct, IPixel + { + this.Result = new DrawImageProcessor( + image, + this.definition.Location, + this.definition.ColorBlendingMode, + this.definition.AlphaCompositionMode, + this.definition.Opacity + ); + } + } + } + /// /// Combines two images together by blending the pixels. /// - /// The pixel format of destination image. - /// The pixel format of source image. - internal class DrawImageProcessor : ImageProcessor - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel + /// The pixel format of destination image. + /// The pixel format of source image. + internal class DrawImageProcessor : ImageProcessor + where TPixelBg : struct, IPixel + where TPixelFg : struct, IPixel { /// /// Initializes a new instance of the class. @@ -30,20 +106,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// The blending mode to use when drawing the image. /// The Alpha blending mode to use when drawing the image. /// The opacity of the image to blend. Must be between 0 and 1. - public DrawImageProcessor(Image image, Point location, PixelColorBlendingMode colorBlendingMode, PixelAlphaCompositionMode alphaCompositionMode, float opacity) + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); this.Image = image; this.Opacity = opacity; - this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); + this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); this.Location = location; } /// /// Gets the image to blend /// - public Image Image { get; } + public Image Image { get; } /// /// Gets the opacity of the image to blend @@ -53,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Gets the pixel blender /// - public PixelBlender Blender { get; } + public PixelBlender Blender { get; } /// /// Gets the location to draw the blended image @@ -61,10 +142,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing public Point Location { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) { - Image targetImage = this.Image; - PixelBlender blender = this.Blender; + Image targetImage = this.Image; + PixelBlender blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. @@ -84,7 +168,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing // not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) { - throw new ImageProcessingException("Cannot draw image because the source image does not overlap the target image."); + throw new ImageProcessingException( + "Cannot draw image because the source image does not overlap the target image."); } ParallelHelper.IterateRows( @@ -94,10 +179,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { for (int y = rows.Min; y < rows.Max; y++) { - Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(configuration, background, background, foreground, this.Opacity); + blender.Blend(configuration, background, background, foreground, this.Opacity); } }); } From 3b7a74141f259f70da6826426f57c105ddf6899e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 02:13:16 +0200 Subject: [PATCH 19/27] DrawImageOfDifferentPixelType test cases --- .../Drawing/DrawImageTests.cs | 22 +++++++++++++++++-- tests/Images/External | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index e48a0b0ae3..cb44651d6f 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -96,8 +96,26 @@ namespace SixLabors.ImageSharp.Tests.Drawing testInfo); } } - - + + [Theory] + [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] + public void DrawImageOfDifferentPixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + byte[] brushData = TestFile.Create(TestImages.Png.Ducky).Bytes; + + using (Image image = provider.GetImage()) + using (Image brushImage = provider.PixelType == PixelTypes.Rgba32 + ? (Image)Image.Load(brushData) + : Image.Load(brushData)) + { + image.Mutate(c => c.DrawImage(brushImage, 0.5f)); + + image.DebugSave(provider, appendSourceFileOrDescription: false); + image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + } + } + [Theory] [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 0, 0)] [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 25)] diff --git a/tests/Images/External b/tests/Images/External index 9d1d9dd537..82f082ed3b 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 9d1d9dd53755007ee812907f64304d1925c6a91a +Subproject commit 82f082ed3b47cc21b38dda9c5f8dda06dca5233a From b7dadca8b0434ae2e46acac1dbd07efab0234386 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 23:52:03 +0200 Subject: [PATCH 20/27] clean-up drawing processors --- .../ImageSharp.Drawing.csproj | 2 +- .../Processing/BrushApplicator.cs | 2 +- .../Processing/PatternBrush.cs | 2 +- .../Processors/Drawing/DrawImageProcessor.cs | 131 +---- .../DrawImageProcessor{TPixelBg,TPixelFg}.cs | 111 +++++ .../Processors/Drawing/FillProcessor.cs | 128 +---- .../Drawing/FillProcessor{TPixel}.cs | 118 +++++ .../Processors/Drawing/FillRegionProcessor.cs | 197 +------- .../Drawing/FillRegionProcessor{TPixel}.cs | 195 ++++++++ .../Processors/Text/DrawTextProcessor.cs | 445 +---------------- .../Text/DrawTextProcessor{TPixel}.cs | 446 ++++++++++++++++++ .../Processing/RadialGradientBrush.cs | 1 - .../Processing/SolidBrush.cs | 4 +- .../Processing/TextGraphicsOptions.cs | 328 +++++++------ src/ImageSharp/Image.cs | 2 +- src/ImageSharp/ImageSharp.csproj | 2 +- 16 files changed, 1088 insertions(+), 1026 deletions(-) create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index fdeb27a770..722ef33ff0 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -40,9 +40,9 @@ + - diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs index 0c6e0d3b40..7e75d7effc 100644 --- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs +++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the blend percentage /// - protected GraphicsOptions Options { get; private set; } + protected GraphicsOptions Options { get; } /// /// Gets the color for a single pixel. diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs index 21690055e1..a7a6785b92 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. internal PatternBrush(PatternBrush brush) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 0fbef9afea..54b7315b21 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -1,20 +1,29 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Buffers; using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Combines two images together by blending the pixels. + /// public class DrawImageProcessor : IImageProcessor { + /// + /// Initializes a new instance of the class. + /// + /// The image to blend. + /// The location to draw the blended image. + /// The blending mode to use when drawing the image. + /// The Alpha blending mode to use when drawing the image. + /// The opacity of the image to blend. public DrawImageProcessor( Image image, Point location, @@ -30,27 +39,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } /// - /// Gets the image to blend + /// Gets the image to blend. /// public Image Image { get; } /// - /// Gets the location to draw the blended image + /// Gets the location to draw the blended image. /// public Point Location { get; } - + /// /// Gets the blending mode to use when drawing the image. /// public PixelColorBlendingMode ColorBlendingMode { get; } - + /// /// Gets the Alpha blending mode to use when drawing the image. /// public PixelAlphaCompositionMode AlphaCompositionMode { get; } - + /// - /// Gets the opacity of the image to blend + /// Gets the opacity of the image to blend. /// public float Opacity { get; } @@ -74,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } public IImageProcessor Result { get; private set; } - + public void Visit(Image image) where TPixelFg : struct, IPixel { @@ -83,108 +92,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing this.definition.Location, this.definition.ColorBlendingMode, this.definition.AlphaCompositionMode, - this.definition.Opacity - ); + this.definition.Opacity); } } } - - /// - /// Combines two images together by blending the pixels. - /// - /// The pixel format of destination image. - /// The pixel format of source image. - internal class DrawImageProcessor : ImageProcessor - where TPixelBg : struct, IPixel - where TPixelFg : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The blending mode to use when drawing the image. - /// The Alpha blending mode to use when drawing the image. - /// The opacity of the image to blend. Must be between 0 and 1. - public DrawImageProcessor( - Image image, - Point location, - PixelColorBlendingMode colorBlendingMode, - PixelAlphaCompositionMode alphaCompositionMode, - float opacity) - { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.Image = image; - this.Opacity = opacity; - this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); - this.Location = location; - } - - /// - /// Gets the image to blend - /// - public Image Image { get; } - - /// - /// Gets the opacity of the image to blend - /// - public float Opacity { get; } - - /// - /// Gets the pixel blender - /// - public PixelBlender Blender { get; } - - /// - /// Gets the location to draw the blended image - /// - public Point Location { get; } - - /// - protected override void OnFrameApply( - ImageFrame source, - Rectangle sourceRectangle, - Configuration configuration) - { - Image targetImage = this.Image; - PixelBlender blender = this.Blender; - int locationY = this.Location.Y; - - // Align start/end positions. - Rectangle bounds = targetImage.Bounds(); - - int minX = Math.Max(this.Location.X, sourceRectangle.X); - int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); - int targetX = minX - this.Location.X; - - int minY = Math.Max(this.Location.Y, sourceRectangle.Y); - int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - // not a valid operation because rectangle does not overlap with this image. - if (workingRect.Width <= 0 || workingRect.Height <= 0) - { - throw new ImageProcessingException( - "Cannot draw image because the source image does not overlap the target image."); - } - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = - targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(configuration, background, background, foreground, this.Opacity); - } - }); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs new file mode 100644 index 0000000000..21599bf787 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs @@ -0,0 +1,111 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Combines two images together by blending the pixels. + /// + /// The pixel format of destination image. + /// The pixel format of source image. + internal class DrawImageProcessor : ImageProcessor + where TPixelBg : struct, IPixel + where TPixelFg : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The blending mode to use when drawing the image. + /// The Alpha blending mode to use when drawing the image. + /// The opacity of the image to blend. Must be between 0 and 1. + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) + { + Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); + + this.Image = image; + this.Opacity = opacity; + this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); + this.Location = location; + } + + /// + /// Gets the image to blend + /// + public Image Image { get; } + + /// + /// Gets the opacity of the image to blend + /// + public float Opacity { get; } + + /// + /// Gets the pixel blender + /// + public PixelBlender Blender { get; } + + /// + /// Gets the location to draw the blended image + /// + public Point Location { get; } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + Image targetImage = this.Image; + PixelBlender blender = this.Blender; + int locationY = this.Location.Y; + + // Align start/end positions. + Rectangle bounds = targetImage.Bounds(); + + int minX = Math.Max(this.Location.X, sourceRectangle.X); + int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); + int targetX = minX - this.Location.X; + + int minY = Math.Max(this.Location.Y, sourceRectangle.Y); + int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); + + int width = maxX - minX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + // not a valid operation because rectangle does not overlap with this image. + if (workingRect.Width <= 0 || workingRect.Height <= 0) + { + throw new ImageProcessingException( + "Cannot draw image because the source image does not overlap the target image."); + } + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = + targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); + blender.Blend(configuration, background, background, foreground, this.Opacity); + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index 8ea1c48cc2..d6254c7cfb 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -1,28 +1,38 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Defines a processor to fill an with the given + /// using blending defined by the given . + /// public class FillProcessor : IImageProcessor { + /// + /// Initializes a new instance of the class. + /// + /// The brush to use for filling. + /// The defining how to blend the brush pixels over the image pixels. public FillProcessor(IBrush brush, GraphicsOptions options) { this.Brush = brush; this.Options = options; } + /// + /// Gets the used for filling the destination image. + /// public IBrush Brush { get; } - + + /// + /// Gets the defining how to blend the brush pixels over the image pixels. + /// public GraphicsOptions Options { get; } /// @@ -32,108 +42,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing return new FillProcessor(this); } } - - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class FillProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillProcessor definition; - - public FillProcessor(FillProcessor definition) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - IBrush brush = this.definition.Brush; - GraphicsOptions options = this.definition.Options; - - // If there's no reason for blending, then avoid it. - if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) - { - ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); - - TPixel colorPixel = solidBrush.Color.ToPixel(); - - ParallelHelper.IterateRows( - workingRect, - parallelSettings, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); - } - }); - } - else - { - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - using (BrushApplicator applicator = brush.CreateApplicator( - source, - sourceRectangle, - options)) - { - amount.GetSpan().Fill(1f); - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - int offsetY = y - startY; - int offsetX = minX - startX; - - applicator.Apply(amount.GetSpan(), offsetX, offsetY); - } - }); - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush == null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs new file mode 100644 index 0000000000..68aef82e2d --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs @@ -0,0 +1,118 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class FillProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillProcessor definition; + + public FillProcessor(FillProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + int width = maxX - minX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + IBrush brush = this.definition.Brush; + GraphicsOptions options = this.definition.Options; + + // If there's no reason for blending, then avoid it. + if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) + { + ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + + TPixel colorPixel = solidBrush.Color.ToPixel(); + + ParallelHelper.IterateRows( + workingRect, + parallelSettings, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); + } + }); + } + else + { + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) + using (BrushApplicator applicator = brush.CreateApplicator( + source, + sourceRectangle, + options)) + { + amount.GetSpan().Fill(1f); + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + int offsetY = y - startY; + int offsetX = minX - startX; + + applicator.Apply(amount.GetSpan(), offsetX, offsetY); + } + }); + } + } + } + + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + { + solidBrush = this.definition.Brush as SolidBrush; + + if (solidBrush == null) + { + return false; + } + + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs index 3653102efa..1b207d4cd4 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs @@ -1,18 +1,16 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Utils; using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Defines a processor to fill pixels withing a given + /// with the given and blending defined by the given . + /// public class FillRegionProcessor : IImageProcessor { /// @@ -29,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } /// - /// Gets the brush. + /// Gets the used for filling the destination image. /// public IBrush Brush { get; } @@ -39,11 +37,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing public Region Region { get; } /// - /// Gets the options. + /// Gets the defining how to blend the brush pixels over the image pixels. /// - /// - /// The options. - /// public GraphicsOptions Options { get; } /// @@ -53,184 +48,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing return new FillRegionProcessor(this); } } - - /// - /// Using a brush and a shape fills shape with contents of brush the - /// - /// The type of the color. - /// - internal class FillRegionProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillRegionProcessor definition; - - public FillRegionProcessor(FillRegionProcessor definition) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - GraphicsOptions options = this.definition.Options; - IBrush brush = this.definition.Brush; - Region region = this.definition.Region; - Rectangle rect = region.Bounds; - - // Align start/end positions. - int minX = Math.Max(0, rect.Left); - int maxX = Math.Min(source.Width, rect.Right); - int minY = Math.Max(0, rect.Top); - int maxY = Math.Min(source.Height, rect.Bottom); - if (minX >= maxX) - { - return; // no effect inside image; - } - - if (minY >= maxY) - { - return; // no effect inside image; - } - - 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 align with the pixel grid. - float offset = 0.5f; - if (options.Antialias) - { - offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = options.AntialiasSubpixelDepth; - if (subpixelCount < 4) - { - subpixelCount = 4; - } - } - - using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) - { - int scanlineWidth = maxX - minX; - using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) - using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth)) - { - bool scanlineDirty = true; - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - - Span buffer = bBuffer.GetSpan(); - Span scanline = bScanline.GetSpan(); - - bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); - TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; - - for (int y = minY; y < maxY; y++) - { - if (scanlineDirty) - { - scanline.Clear(); - scanlineDirty = false; - } - - float yPlusOne = y + 1; - for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - int pointsFound = region.Scan(subPixel + offset, buffer, configuration); - if (pointsFound == 0) - { - // nothing on this line, skip - continue; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound; point += 2) - { - // points will be paired up - float scanStart = buffer[point] - minX; - float scanEnd = buffer[point + 1] - minX; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!options.Antialias) - { - bool hasOnes = false; - bool hasZeros = false; - for (int x = 0; x < scanlineWidth; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - hasOnes = true; - } - else - { - scanline[x] = 0; - hasZeros = true; - } - } - - if (isSolidBrushWithoutBlending && hasOnes != hasZeros) - { - if (hasOnes) - { - source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); - } - - continue; - } - } - - applicator.Apply(scanline, minX, y); - } - } - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush == null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs new file mode 100644 index 0000000000..d5778c865f --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs @@ -0,0 +1,195 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Utils; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Using a brush and a shape fills shape with contents of brush the + /// + /// The type of the color. + /// + internal class FillRegionProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillRegionProcessor definition; + + public FillRegionProcessor(FillRegionProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + GraphicsOptions options = this.definition.Options; + IBrush brush = this.definition.Brush; + Region region = this.definition.Region; + Rectangle rect = region.Bounds; + + // Align start/end positions. + int minX = Math.Max(0, rect.Left); + int maxX = Math.Min(source.Width, rect.Right); + int minY = Math.Max(0, rect.Top); + int maxY = Math.Min(source.Height, rect.Bottom); + if (minX >= maxX) + { + return; // no effect inside image; + } + + if (minY >= maxY) + { + return; // no effect inside image; + } + + 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 align with the pixel grid. + float offset = 0.5f; + if (options.Antialias) + { + offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. + subpixelCount = options.AntialiasSubpixelDepth; + if (subpixelCount < 4) + { + subpixelCount = 4; + } + } + + using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) + { + int scanlineWidth = maxX - minX; + using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) + using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth)) + { + bool scanlineDirty = true; + float subpixelFraction = 1f / subpixelCount; + float subpixelFractionPoint = subpixelFraction / subpixelCount; + + Span buffer = bBuffer.GetSpan(); + Span scanline = bScanline.GetSpan(); + + bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; + + for (int y = minY; y < maxY; y++) + { + if (scanlineDirty) + { + scanline.Clear(); + scanlineDirty = false; + } + + float yPlusOne = y + 1; + for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) + { + int pointsFound = region.Scan(subPixel + offset, buffer, configuration); + if (pointsFound == 0) + { + // nothing on this line, skip + continue; + } + + QuickSort.Sort(buffer.Slice(0, pointsFound)); + + for (int point = 0; point < pointsFound; point += 2) + { + // points will be paired up + float scanStart = buffer[point] - minX; + float scanEnd = buffer[point + 1] - minX; + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); + + if (startX >= 0 && startX < scanline.Length) + { + for (float x = scanStart; x < startX + 1; x += subpixelFraction) + { + scanline[startX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + if (endX >= 0 && endX < scanline.Length) + { + for (float x = endX; x < scanEnd; x += subpixelFraction) + { + scanline[endX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + int nextX = startX + 1; + endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge + nextX = Math.Max(nextX, 0); + for (int x = nextX; x < endX; x++) + { + scanline[x] += subpixelFraction; + scanlineDirty = true; + } + } + } + + if (scanlineDirty) + { + if (!options.Antialias) + { + bool hasOnes = false; + bool hasZeros = false; + for (int x = 0; x < scanlineWidth; x++) + { + if (scanline[x] >= 0.5) + { + scanline[x] = 1; + hasOnes = true; + } + else + { + scanline[x] = 0; + hasZeros = true; + } + } + + if (isSolidBrushWithoutBlending && hasOnes != hasZeros) + { + if (hasOnes) + { + source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); + } + + continue; + } + } + + applicator.Apply(scanline, minX, y); + } + } + } + } + } + + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + { + solidBrush = this.definition.Brush as SolidBrush; + + if (solidBrush == null) + { + return false; + } + + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index d1e28afeb8..40621ce997 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -2,19 +2,16 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers; -using System.Collections.Generic; + using SixLabors.Fonts; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Utils; -using SixLabors.Memory; using SixLabors.Primitives; -using SixLabors.Shapes; namespace SixLabors.ImageSharp.Processing.Processors.Text { + /// + /// Defines a processor to draw text on an . + /// public class DrawTextProcessor : IImageProcessor { /// @@ -45,17 +42,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text } /// - /// Gets the brush. + /// Gets the brush used to fill the glyphs. /// public IBrush Brush { get; } /// - /// Gets the options + /// Gets the defining blending modes and text-specific drawing settings. /// public TextGraphicsOptions Options { get; } /// - /// Gets the text + /// Gets the text to draw. /// public string Text { get; } @@ -81,432 +78,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text return new DrawTextProcessor(this); } } - - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class DrawTextProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private CachingGlyphRenderer textRenderer; - - private readonly DrawTextProcessor definition; - - public DrawTextProcessor(DrawTextProcessor definition) - { - this.definition = definition; - } - - private TextGraphicsOptions Options => this.definition.Options; - - private Font Font => this.definition.Font; - - private PointF Location => this.definition.Location; - - private string Text => this.definition.Text; - - private IPen Pen => this.definition.Pen; - - private IBrush Brush => this.definition.Brush; - - protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) - { - base.BeforeImageApply(source, sourceRectangle); - - // do everything at the image level as we are delegating the processing down to other processors - var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location) - { - ApplyKerning = this.Options.ApplyKerning, - TabWidth = this.Options.TabWidth, - WrappingWidth = this.Options.WrapTextWidth, - HorizontalAlignment = this.Options.HorizontalAlignment, - VerticalAlignment = this.Options.VerticalAlignment - }; - - this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null); - this.textRenderer.Options = (GraphicsOptions)this.Options; - var renderer = new TextRenderer(this.textRenderer); - renderer.RenderText(this.Text, style); - } - - protected override void AfterImageApply(Image source, Rectangle sourceRectangle) - { - base.AfterImageApply(source, sourceRectangle); - this.textRenderer?.Dispose(); - this.textRenderer = null; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - // this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome - Draw(this.textRenderer.FillOperations, this.Brush); - Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); - - void Draw(List operations, IBrush brush) - { - if (operations?.Count > 0) - { - using (BrushApplicator app = brush.CreateApplicator(source, sourceRectangle, this.textRenderer.Options)) - { - foreach (DrawingOperation operation in operations) - { - Buffer2D buffer = operation.Map; - int startY = operation.Location.Y; - int startX = operation.Location.X; - int offSetSpan = 0; - if (startX < 0) - { - offSetSpan = -startX; - startX = 0; - } - - int fistRow = 0; - if (startY < 0) - { - fistRow = -startY; - } - - int maxHeight = source.Height - startY; - int end = Math.Min(operation.Map.Height, maxHeight); - - for (int row = fistRow; row < end; row++) - { - int y = startY + row; - Span span = buffer.GetRowSpan(row).Slice(offSetSpan); - app.Apply(span, startX, y); - } - } - } - } - } - } - - private struct DrawingOperation - { - public Buffer2D Map { get; set; } - - public Point Location { get; set; } - } - - private class CachingGlyphRenderer : IGlyphRenderer, IDisposable - { - // just enough accuracy to allow for 1/8 pixel differences which - // later are accumulated while rendering, but do not grow into full pixel offsets - // The value 8 is benchmarked to: - // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) - // - Cache hit ratio above 60% - private const float AccuracyMultiple = 8; - - private readonly PathBuilder builder; - - private Point currentRenderPosition = default; - private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; - private readonly int offset = 0; - private PointF currentPoint = default(PointF); - - private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> - glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); - - private readonly bool renderOutline = false; - private readonly bool renderFill = false; - private bool rasterizationRequired = false; - - public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) - { - this.MemoryAllocator = memoryAllocator; - this.Pen = pen; - this.renderFill = renderFill; - this.renderOutline = pen != null; - this.offset = 2; - if (this.renderFill) - { - this.FillOperations = new List(size); - } - - if (this.renderOutline) - { - this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2); - this.OutlineOperations = new List(size); - } - - this.builder = new PathBuilder(); - } - - public List FillOperations { get; } - - public List OutlineOperations { get; } - - public MemoryAllocator MemoryAllocator { get; internal set; } - - public IPen Pen { get; internal set; } - - public GraphicsOptions Options { get; internal set; } - - public void BeginFigure() - { - this.builder.StartFigure(); - } - - public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) - { - this.currentRenderPosition = Point.Truncate(bounds.Location); - PointF subPixelOffset = bounds.Location - this.currentRenderPosition; - - subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; - subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; - - // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate - this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = (parameters, subPixelOffset); - - if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) - { - // we have already drawn the glyph vectors skip trying again - this.rasterizationRequired = false; - return false; - } - - // we check to see if we have a render cache and if we do then we render else - this.builder.Clear(); - - // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offet it back - this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); - - this.rasterizationRequired = true; - return true; - } - - public void BeginText(RectangleF bounds) - { - // not concerned about this one - this.OutlineOperations?.Clear(); - this.FillOperations?.Clear(); - } - - public void CubicBezierTo(PointF secondControlPoint, PointF thirdControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); - this.currentPoint = point; - } - - public void Dispose() - { - foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) - { - kv.Value.Dispose(); - } - - this.glyphData.Clear(); - } - - public void EndFigure() - { - this.builder.CloseFigure(); - } - - public void EndGlyph() - { - GlyphRenderData renderData = default; - - // has the glyoh been rendedered already???? - if (this.rasterizationRequired) - { - IPath path = this.builder.Build(); - - if (this.renderFill) - { - renderData.FillMap = this.Render(path); - } - - if (this.renderOutline) - { - if (this.Pen.StrokePattern.Length == 0) - { - path = path.GenerateOutline(this.Pen.StrokeWidth); - } - else - { - path = path.GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); - } - - renderData.OutlineMap = this.Render(path); - } - - this.glyphData[this.currentGlyphRenderParams] = renderData; - } - else - { - renderData = this.glyphData[this.currentGlyphRenderParams]; - } - - if (this.renderFill) - { - this.FillOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.FillMap - }); - } - - if (this.renderOutline) - { - this.OutlineOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.OutlineMap - }); - } - } - - private Buffer2D Render(IPath path) - { - Size size = Rectangle.Ceiling(path.Bounds).Size; - size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); - - float subpixelCount = 4; - 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) - { - subpixelCount = 4; - } - } - - // take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it. - Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean); - - using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections)) - using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width)) - { - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - - for (int y = 0; y <= size.Height; y++) - { - Span scanline = fullBuffer.GetRowSpan(y); - bool scanlineDirty = false; - float yPlusOne = y + 1; - - for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - var start = new PointF(path.Bounds.Left - 1, subPixel); - var end = new PointF(path.Bounds.Right + 1, subPixel); - Span intersectionSpan = rowIntersectionBuffer.GetSpan(); - Span buffer = bufferBacking.GetSpan(); - int pointsFound = path.FindIntersections(start, end, intersectionSpan); - - if (pointsFound == 0) - { - // nothing on this line skip - continue; - } - - for (int i = 0; i < pointsFound && i < intersectionSpan.Length; i++) - { - buffer[i] = intersectionSpan[i].X; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound; point += 2) - { - // points will be paired up - float scanStart = buffer[point]; - float scanEnd = buffer[point + 1]; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!this.Options.Antialias) - { - for (int x = 0; x < size.Width; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - } - else - { - scanline[x] = 0; - } - } - } - } - } - } - - return fullBuffer; - } - - public void EndText() - { - } - - public void LineTo(PointF point) - { - this.builder.AddLine(this.currentPoint, point); - this.currentPoint = point; - } - - public void MoveTo(PointF point) - { - this.builder.StartFigure(); - this.currentPoint = point; - } - - public void QuadraticBezierTo(PointF secondControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, point); - this.currentPoint = point; - } - - private struct GlyphRenderData : IDisposable - { - public Buffer2D FillMap; - - public Buffer2D OutlineMap; - - public void Dispose() - { - this.FillMap?.Dispose(); - this.OutlineMap?.Dispose(); - } - } - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs new file mode 100644 index 0000000000..9fb52d6bc3 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs @@ -0,0 +1,446 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Collections.Generic; + +using SixLabors.Fonts; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Utils; +using SixLabors.Memory; +using SixLabors.Primitives; +using SixLabors.Shapes; + +namespace SixLabors.ImageSharp.Processing.Processors.Text +{ + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class DrawTextProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private CachingGlyphRenderer textRenderer; + + private readonly DrawTextProcessor definition; + + public DrawTextProcessor(DrawTextProcessor definition) + { + this.definition = definition; + } + + private TextGraphicsOptions Options => this.definition.Options; + + private Font Font => this.definition.Font; + + private PointF Location => this.definition.Location; + + private string Text => this.definition.Text; + + private IPen Pen => this.definition.Pen; + + private IBrush Brush => this.definition.Brush; + + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + { + base.BeforeImageApply(source, sourceRectangle); + + // do everything at the image level as we are delegating the processing down to other processors + var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location) + { + ApplyKerning = this.Options.ApplyKerning, + TabWidth = this.Options.TabWidth, + WrappingWidth = this.Options.WrapTextWidth, + HorizontalAlignment = this.Options.HorizontalAlignment, + VerticalAlignment = this.Options.VerticalAlignment + }; + + this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null); + this.textRenderer.Options = (GraphicsOptions)this.Options; + var renderer = new TextRenderer(this.textRenderer); + renderer.RenderText(this.Text, style); + } + + protected override void AfterImageApply(Image source, Rectangle sourceRectangle) + { + base.AfterImageApply(source, sourceRectangle); + this.textRenderer?.Dispose(); + this.textRenderer = null; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + // this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome + Draw(this.textRenderer.FillOperations, this.Brush); + Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); + + void Draw(List operations, IBrush brush) + { + if (operations?.Count > 0) + { + using (BrushApplicator app = brush.CreateApplicator(source, sourceRectangle, this.textRenderer.Options)) + { + foreach (DrawingOperation operation in operations) + { + Buffer2D buffer = operation.Map; + int startY = operation.Location.Y; + int startX = operation.Location.X; + int offSetSpan = 0; + if (startX < 0) + { + offSetSpan = -startX; + startX = 0; + } + + int fistRow = 0; + if (startY < 0) + { + fistRow = -startY; + } + + int maxHeight = source.Height - startY; + int end = Math.Min(operation.Map.Height, maxHeight); + + for (int row = fistRow; row < end; row++) + { + int y = startY + row; + Span span = buffer.GetRowSpan(row).Slice(offSetSpan); + app.Apply(span, startX, y); + } + } + } + } + } + } + + private struct DrawingOperation + { + public Buffer2D Map { get; set; } + + public Point Location { get; set; } + } + + private class CachingGlyphRenderer : IGlyphRenderer, IDisposable + { + // just enough accuracy to allow for 1/8 pixel differences which + // later are accumulated while rendering, but do not grow into full pixel offsets + // The value 8 is benchmarked to: + // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) + // - Cache hit ratio above 60% + private const float AccuracyMultiple = 8; + + private readonly PathBuilder builder; + + private Point currentRenderPosition = default; + private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; + private readonly int offset = 0; + private PointF currentPoint = default(PointF); + + private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> + glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); + + private readonly bool renderOutline = false; + private readonly bool renderFill = false; + private bool rasterizationRequired = false; + + public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) + { + this.MemoryAllocator = memoryAllocator; + this.Pen = pen; + this.renderFill = renderFill; + this.renderOutline = pen != null; + this.offset = 2; + if (this.renderFill) + { + this.FillOperations = new List(size); + } + + if (this.renderOutline) + { + this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2); + this.OutlineOperations = new List(size); + } + + this.builder = new PathBuilder(); + } + + public List FillOperations { get; } + + public List OutlineOperations { get; } + + public MemoryAllocator MemoryAllocator { get; internal set; } + + public IPen Pen { get; internal set; } + + public GraphicsOptions Options { get; internal set; } + + public void BeginFigure() + { + this.builder.StartFigure(); + } + + public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) + { + this.currentRenderPosition = Point.Truncate(bounds.Location); + PointF subPixelOffset = bounds.Location - this.currentRenderPosition; + + subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; + subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; + + // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate + this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); + this.currentGlyphRenderParams = (parameters, subPixelOffset); + + if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) + { + // we have already drawn the glyph vectors skip trying again + this.rasterizationRequired = false; + return false; + } + + // we check to see if we have a render cache and if we do then we render else + this.builder.Clear(); + + // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offet it back + this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); + + this.rasterizationRequired = true; + return true; + } + + public void BeginText(RectangleF bounds) + { + // not concerned about this one + this.OutlineOperations?.Clear(); + this.FillOperations?.Clear(); + } + + public void CubicBezierTo(PointF secondControlPoint, PointF thirdControlPoint, PointF point) + { + this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); + this.currentPoint = point; + } + + public void Dispose() + { + foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) + { + kv.Value.Dispose(); + } + + this.glyphData.Clear(); + } + + public void EndFigure() + { + this.builder.CloseFigure(); + } + + public void EndGlyph() + { + GlyphRenderData renderData = default; + + // has the glyoh been rendedered already???? + if (this.rasterizationRequired) + { + IPath path = this.builder.Build(); + + if (this.renderFill) + { + renderData.FillMap = this.Render(path); + } + + if (this.renderOutline) + { + if (this.Pen.StrokePattern.Length == 0) + { + path = path.GenerateOutline(this.Pen.StrokeWidth); + } + else + { + path = path.GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); + } + + renderData.OutlineMap = this.Render(path); + } + + this.glyphData[this.currentGlyphRenderParams] = renderData; + } + else + { + renderData = this.glyphData[this.currentGlyphRenderParams]; + } + + if (this.renderFill) + { + this.FillOperations.Add(new DrawingOperation + { + Location = this.currentRenderPosition, + Map = renderData.FillMap + }); + } + + if (this.renderOutline) + { + this.OutlineOperations.Add(new DrawingOperation + { + Location = this.currentRenderPosition, + Map = renderData.OutlineMap + }); + } + } + + private Buffer2D Render(IPath path) + { + Size size = Rectangle.Ceiling(path.Bounds).Size; + size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); + + float subpixelCount = 4; + 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) + { + subpixelCount = 4; + } + } + + // take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it. + Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean); + + using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections)) + using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width)) + { + float subpixelFraction = 1f / subpixelCount; + float subpixelFractionPoint = subpixelFraction / subpixelCount; + + for (int y = 0; y <= size.Height; y++) + { + Span scanline = fullBuffer.GetRowSpan(y); + bool scanlineDirty = false; + float yPlusOne = y + 1; + + for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) + { + var start = new PointF(path.Bounds.Left - 1, subPixel); + var end = new PointF(path.Bounds.Right + 1, subPixel); + Span intersectionSpan = rowIntersectionBuffer.GetSpan(); + Span buffer = bufferBacking.GetSpan(); + int pointsFound = path.FindIntersections(start, end, intersectionSpan); + + if (pointsFound == 0) + { + // nothing on this line skip + continue; + } + + for (int i = 0; i < pointsFound && i < intersectionSpan.Length; i++) + { + buffer[i] = intersectionSpan[i].X; + } + + QuickSort.Sort(buffer.Slice(0, pointsFound)); + + for (int point = 0; point < pointsFound; point += 2) + { + // points will be paired up + float scanStart = buffer[point]; + float scanEnd = buffer[point + 1]; + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); + + if (startX >= 0 && startX < scanline.Length) + { + for (float x = scanStart; x < startX + 1; x += subpixelFraction) + { + scanline[startX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + if (endX >= 0 && endX < scanline.Length) + { + for (float x = endX; x < scanEnd; x += subpixelFraction) + { + scanline[endX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + int nextX = startX + 1; + endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge + nextX = Math.Max(nextX, 0); + for (int x = nextX; x < endX; x++) + { + scanline[x] += subpixelFraction; + scanlineDirty = true; + } + } + } + + if (scanlineDirty) + { + if (!this.Options.Antialias) + { + for (int x = 0; x < size.Width; x++) + { + if (scanline[x] >= 0.5) + { + scanline[x] = 1; + } + else + { + scanline[x] = 0; + } + } + } + } + } + } + + return fullBuffer; + } + + public void EndText() + { + } + + public void LineTo(PointF point) + { + this.builder.AddLine(this.currentPoint, point); + this.currentPoint = point; + } + + public void MoveTo(PointF point) + { + this.builder.StartFigure(); + this.currentPoint = point; + } + + public void QuadraticBezierTo(PointF secondControlPoint, PointF point) + { + this.builder.AddBezier(this.currentPoint, secondControlPoint, point); + this.currentPoint = point; + } + + private struct GlyphRenderData : IDisposable + { + public Buffer2D FillMap; + + public Buffer2D OutlineMap; + + public void Dispose() + { + this.FillMap?.Dispose(); + this.OutlineMap?.Dispose(); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs index 84a97e7d1f..aac0f2e7bd 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs @@ -12,7 +12,6 @@ namespace SixLabors.ImageSharp.Processing /// A Circular Gradient Brush, defined by center point and radius. /// public sealed class RadialGradientBrush : GradientBrushBase - { private readonly PointF center; diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs index 75ca5aa7e8..c62566f6b7 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing private readonly Color color; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. public SolidBrush(Color color) @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing where TPixel : struct, IPixel { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// The color. diff --git a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs index 3c682a761b..7f7332a57c 100644 --- a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs @@ -1,169 +1,163 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Options for influencing the drawing functions. - /// - public struct TextGraphicsOptions - { - private const int DefaultTextDpi = 72; - - /// - /// Represents the default . - /// - public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - - private bool? applyKerning; - - private float? tabWidth; - - private float? dpiX; - - private float? dpiY; - - private PixelColorBlendingMode colorBlendingMode; - - private PixelAlphaCompositionMode alphaCompositionMode; - - private float wrapTextWidth; - - private HorizontalAlignment? horizontalAlignment; - - private VerticalAlignment? verticalAlignment; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public TextGraphicsOptions(bool enableAntialiasing) - { - this.applyKerning = true; - this.tabWidth = 4; - this.wrapTextWidth = 0; - this.horizontalAlignment = HorizontalAlignment.Left; - this.verticalAlignment = VerticalAlignment.Top; - - this.antialiasSubpixelDepth = 16; - this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialias = enableAntialiasing; - this.dpiX = DefaultTextDpi; - this.dpiY = DefaultTextDpi; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode { get => this.colorBlendingMode; set => this.colorBlendingMode = value; } - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode { get => this.alphaCompositionMode; set => this.alphaCompositionMode = value; } - - /// - /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. - /// - public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } - - /// - /// Gets or sets a value indicating the number of space widths a tab should lock to. - /// - public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } - - /// - /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. - /// - public float WrapTextWidth { get => this.wrapTextWidth; set => this.wrapTextWidth = value; } - - /// - /// Gets or sets a value indicating the DPI to render text along the X axis. - /// - public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } - - /// - /// Gets or sets a value indicating the DPI to render text along the Y axis. - /// - public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// If is greater than zero it will align relative to the space - /// defined by the location and width, if equals zero, and thus - /// wrapping disabled, then the alignment is relative to the drawing location. - /// - public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// - public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } - - /// - /// Performs an implicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static implicit operator TextGraphicsOptions(GraphicsOptions options) - { - return new TextGraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - blendPercentage = options.BlendPercentage, - colorBlendingMode = options.ColorBlendingMode, - alphaCompositionMode = options.AlphaCompositionMode - }; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static explicit operator GraphicsOptions(TextGraphicsOptions options) - { - return new GraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.Fonts; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Options for influencing the drawing functions. + /// + public struct TextGraphicsOptions + { + private const int DefaultTextDpi = 72; + + /// + /// Represents the default . + /// + public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + + private bool? applyKerning; + + private float? tabWidth; + + private float? dpiX; + + private float? dpiY; + + private HorizontalAlignment? horizontalAlignment; + + private VerticalAlignment? verticalAlignment; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public TextGraphicsOptions(bool enableAntialiasing) + { + this.applyKerning = true; + this.tabWidth = 4; + this.WrapTextWidth = 0; + this.horizontalAlignment = HorizontalAlignment.Left; + this.verticalAlignment = VerticalAlignment.Top; + + this.antialiasSubpixelDepth = 16; + this.ColorBlendingMode = PixelColorBlendingMode.Normal; + this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialias = enableAntialiasing; + this.dpiX = DefaultTextDpi; + this.dpiY = DefaultTextDpi; + } + + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode { get; set; } + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } + + /// + /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. + /// + public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } + + /// + /// Gets or sets a value indicating the number of space widths a tab should lock to. + /// + public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } + + /// + /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. + /// + public float WrapTextWidth { get; set; } + + /// + /// Gets or sets a value indicating the DPI to render text along the X axis. + /// + public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } + + /// + /// Gets or sets a value indicating the DPI to render text along the Y axis. + /// + public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// If is greater than zero it will align relative to the space + /// defined by the location and width, if equals zero, and thus + /// wrapping disabled, then the alignment is relative to the drawing location. + /// + public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// + public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } + + /// + /// Performs an implicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static implicit operator TextGraphicsOptions(GraphicsOptions options) + { + return new TextGraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + blendPercentage = options.BlendPercentage, + ColorBlendingMode = options.ColorBlendingMode, + AlphaCompositionMode = options.AlphaCompositionMode + }; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static explicit operator GraphicsOptions(TextGraphicsOptions options) + { + return new GraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode, - BlendPercentage = options.BlendPercentage - }; - } - } + AlphaCompositionMode = options.AlphaCompositionMode, + BlendPercentage = options.BlendPercentage + }; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index db03281064..3f3d6a62f7 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp EncodeVisitor visitor = new EncodeVisitor(encoder, stream); this.AcceptVisitor(visitor); } - + /// /// Returns a copy of the image in the given pixel format. /// diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 4abe2f57a2..1b213c26dc 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -41,7 +41,7 @@ - + From d2ea0056c4fe9d28b983ed0c0de4086106d9b665 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 23:59:50 +0200 Subject: [PATCH 21/27] fix remaining stylecop issues --- .../Processing/DrawingHelpers.cs | 7 ++- .../Extensions/DrawPathExtensions.cs | 58 +++++++++++-------- .../Extensions/FillPathExtensions.cs | 33 +++++------ .../Extensions/FillRegionExtensions.cs | 54 ++++++++--------- .../Processing/GradientBrushBase.cs | 2 +- .../Processing/GradientRepetitionMode.cs | 6 +- src/ImageSharp.Drawing/Processing/IBrush.cs | 4 +- src/ImageSharp.Drawing/Processing/IPen.cs | 5 +- .../Processing/ImageBrush.cs | 2 +- .../Processing/LinearGradientBrush.cs | 18 ++++-- 10 files changed, 102 insertions(+), 87 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs index 314b65f7e7..b4ce0c5cba 100644 --- a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs +++ b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Processing { internal static class DrawingHelpers { + /// + /// Convert a to a of the given pixel type. + /// public static DenseMatrix ToPixelMatrix(this DenseMatrix colorMatrix, Configuration configuration) where TPixel : struct, IPixel { diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs index f231f1baae..efafdde5ab 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs @@ -15,80 +15,90 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The image this method extends. /// The options. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) - - => source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + IPath path) => + source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); /// /// Draws the outline of the polygon with the provided pen. /// - /// The image this method extends. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) - - => source.Draw(GraphicsOptions.Default, pen, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) => + source.Draw(GraphicsOptions.Default, pen, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) - - => source.Draw(options, new Pen(brush, thickness), path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + IPath path) => + source.Draw(options, new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The brush. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) - - => source.Draw(new Pen(brush, thickness), path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + IPath path) => + source.Draw(new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The options. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, Color color, float thickness, IPath path) - - => source.Draw(options, new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + IPath path) => + source.Draw(options, new SolidBrush(color), thickness, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, Color color, float thickness, IPath path) - - => source.Draw(new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + IPath path) => + source.Draw(new SolidBrush(color), thickness, path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs index 7cf67612a2..718016a9e6 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.Shapes; @@ -15,51 +14,51 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) - - => source.Fill(options, brush, new ShapeRegion(path)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + IPath path) => + source.Fill(options, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) - - => source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) => + source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, IPath path) - - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + IPath path) => + source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) - - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) => + source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs index 457ad98b0c..294e575140 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Drawing; @@ -15,85 +14,82 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image with the specified brush. /// - /// The image this method extends. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) - - => source.Fill(GraphicsOptions.Default, brush); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) => + source.Fill(GraphicsOptions.Default, brush); /// /// Flood fills the image with the specified color. /// - /// The image this method extends. /// The color. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) - - => source.Fill(new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) => + source.Fill(new SolidBrush(color)); /// /// Flood fills the image with in the region with the specified brush. /// - /// The image this method extends. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) - - => source.Fill(GraphicsOptions.Default, brush, region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) => + source.Fill(GraphicsOptions.Default, brush, region); /// /// Flood fills the image with in the region with the specified color. /// - /// The image this method extends. /// The options. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, Region region) - - => source.Fill(options, new SolidBrush(color), region); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + Region region) => + source.Fill(options, new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified color. /// - /// The image this method extends. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) - - => source.Fill(new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) => + source.Fill(new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) - - => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + Region region) => + source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); /// /// Flood fills the image with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) - - => source.ApplyProcessor(new FillProcessor(brush, options)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush) => + source.ApplyProcessor(new FillProcessor(brush, options)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs index a877ea96cd..6e1e0086da 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for gradient brush applicators /// - protected abstract class GradientBrushApplicatorBase : BrushApplicator + internal abstract class GradientBrushApplicatorBase : BrushApplicator where TPixel : struct, IPixel { private readonly ColorStop[] colorStops; diff --git a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs index c156153be5..6aed8a030c 100644 --- a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs +++ b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs @@ -21,16 +21,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Reflect the gradient. - /// Similar to , but each other repetition uses inverse order of s. + /// Similar to , but each other repetition uses inverse order of s. /// Used on a Black-White gradient, Reflect leads to Black->{gray}->White->{gray}->White... /// Reflect, /// /// With DontFill a gradient does not touch any pixel beyond it's borders. - /// For the this is beyond the orthogonal through start and end, + /// For the this is beyond the orthogonal through start and end, /// TODO For the cref="PolygonalGradientBrush" it's outside the polygon, - /// For and it's beyond 1.0. + /// For and it's beyond 1.0. /// DontFill } diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs index aa8c25b950..0cd2e20fda 100644 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ b/src/ImageSharp.Drawing/Processing/IBrush.cs @@ -9,16 +9,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Brush represents a logical configuration of a brush which can be used to source pixel colors /// - /// The pixel format. /// /// A brush is a simple class that will return an that will perform the - /// logic for converting a pixel location to a . + /// logic for retrieving pixel values for specific locations. /// public interface IBrush { /// /// Creates the applicator for this brush. /// + /// The pixel type. /// The source image. /// The region the brush will be applied to. /// The graphic options diff --git a/src/ImageSharp.Drawing/Processing/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs index b9e359d601..af7517905d 100644 --- a/src/ImageSharp.Drawing/Processing/IPen.cs +++ b/src/ImageSharp.Drawing/Processing/IPen.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; + using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// Gets the stroke fill. /// IBrush StrokeFill { get; } - + /// /// Gets the width to apply to the stroke /// @@ -26,4 +27,4 @@ namespace SixLabors.ImageSharp.Processing /// ReadOnlySpan StrokePattern { get; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index c2a8d3a261..33f7b831ab 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing } specificImage = this.image.CloneAs(); - + return new ImageBrushApplicator(source, specificImage, region, options, true); } diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index fac43ad634..6eeadee5d6 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -14,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing /// - a set of colors in relative distances to each other. /// public sealed class LinearGradientBrush : GradientBrushBase - { private readonly PointF p1; @@ -39,8 +38,17 @@ namespace SixLabors.ImageSharp.Processing } /// - public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); + public override BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) => + new LinearGradientBrushApplicator( + source, + this.p1, + this.p2, + this.ColorStops, + this.RepetitionMode, + options); /// /// The linear gradient brush applicator. @@ -137,9 +145,7 @@ namespace SixLabors.ImageSharp.Processing float y4 = y + (k * this.alongX); // get distance from (x4,y4) to start - float distance = (float)Math.Sqrt( - Math.Pow(x4 - this.start.X, 2) - + Math.Pow(y4 - this.start.Y, 2)); + float distance = (float)Math.Sqrt(Math.Pow(x4 - this.start.X, 2) + Math.Pow(y4 - this.start.Y, 2)); // get and return ratio float ratio = distance / this.length; From c2e955c064567ab909da6a95d9c20b2031d7c6e9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 14 May 2019 00:01:50 +0200 Subject: [PATCH 22/27] Rgba32.Definitions: use Color instead of NamedColors --- .../Rgba32.Definitions.cs | 284 +++++++++--------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs index 032d0b5464..f9cc3256cd 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs @@ -11,711 +11,711 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Represents a matching the W3C definition that has an hex value of #F0F8FF. /// - public static readonly Rgba32 AliceBlue = NamedColors.AliceBlue; + public static readonly Rgba32 AliceBlue = Color.AliceBlue; /// /// Represents a matching the W3C definition that has an hex value of #FAEBD7. /// - public static readonly Rgba32 AntiqueWhite = NamedColors.AntiqueWhite; + public static readonly Rgba32 AntiqueWhite = Color.AntiqueWhite; /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly Rgba32 Aqua = NamedColors.Aqua; + public static readonly Rgba32 Aqua = Color.Aqua; /// /// Represents a matching the W3C definition that has an hex value of #7FFFD4. /// - public static readonly Rgba32 Aquamarine = NamedColors.Aquamarine; + public static readonly Rgba32 Aquamarine = Color.Aquamarine; /// /// Represents a matching the W3C definition that has an hex value of #F0FFFF. /// - public static readonly Rgba32 Azure = NamedColors.Azure; + public static readonly Rgba32 Azure = Color.Azure; /// /// Represents a matching the W3C definition that has an hex value of #F5F5DC. /// - public static readonly Rgba32 Beige = NamedColors.Beige; + public static readonly Rgba32 Beige = Color.Beige; /// /// Represents a matching the W3C definition that has an hex value of #FFE4C4. /// - public static readonly Rgba32 Bisque = NamedColors.Bisque; + public static readonly Rgba32 Bisque = Color.Bisque; /// /// Represents a matching the W3C definition that has an hex value of #000000. /// - public static readonly Rgba32 Black = NamedColors.Black; + public static readonly Rgba32 Black = Color.Black; /// /// Represents a matching the W3C definition that has an hex value of #FFEBCD. /// - public static readonly Rgba32 BlanchedAlmond = NamedColors.BlanchedAlmond; + public static readonly Rgba32 BlanchedAlmond = Color.BlanchedAlmond; /// /// Represents a matching the W3C definition that has an hex value of #0000FF. /// - public static readonly Rgba32 Blue = NamedColors.Blue; + public static readonly Rgba32 Blue = Color.Blue; /// /// Represents a matching the W3C definition that has an hex value of #8A2BE2. /// - public static readonly Rgba32 BlueViolet = NamedColors.BlueViolet; + public static readonly Rgba32 BlueViolet = Color.BlueViolet; /// /// Represents a matching the W3C definition that has an hex value of #A52A2A. /// - public static readonly Rgba32 Brown = NamedColors.Brown; + public static readonly Rgba32 Brown = Color.Brown; /// /// Represents a matching the W3C definition that has an hex value of #DEB887. /// - public static readonly Rgba32 BurlyWood = NamedColors.BurlyWood; + public static readonly Rgba32 BurlyWood = Color.BurlyWood; /// /// Represents a matching the W3C definition that has an hex value of #5F9EA0. /// - public static readonly Rgba32 CadetBlue = NamedColors.CadetBlue; + public static readonly Rgba32 CadetBlue = Color.CadetBlue; /// /// Represents a matching the W3C definition that has an hex value of #7FFF00. /// - public static readonly Rgba32 Chartreuse = NamedColors.Chartreuse; + public static readonly Rgba32 Chartreuse = Color.Chartreuse; /// /// Represents a matching the W3C definition that has an hex value of #D2691E. /// - public static readonly Rgba32 Chocolate = NamedColors.Chocolate; + public static readonly Rgba32 Chocolate = Color.Chocolate; /// /// Represents a matching the W3C definition that has an hex value of #FF7F50. /// - public static readonly Rgba32 Coral = NamedColors.Coral; + public static readonly Rgba32 Coral = Color.Coral; /// /// Represents a matching the W3C definition that has an hex value of #6495ED. /// - public static readonly Rgba32 CornflowerBlue = NamedColors.CornflowerBlue; + public static readonly Rgba32 CornflowerBlue = Color.CornflowerBlue; /// /// Represents a matching the W3C definition that has an hex value of #FFF8DC. /// - public static readonly Rgba32 Cornsilk = NamedColors.Cornsilk; + public static readonly Rgba32 Cornsilk = Color.Cornsilk; /// /// Represents a matching the W3C definition that has an hex value of #DC143C. /// - public static readonly Rgba32 Crimson = NamedColors.Crimson; + public static readonly Rgba32 Crimson = Color.Crimson; /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly Rgba32 Cyan = NamedColors.Cyan; + public static readonly Rgba32 Cyan = Color.Cyan; /// /// Represents a matching the W3C definition that has an hex value of #00008B. /// - public static readonly Rgba32 DarkBlue = NamedColors.DarkBlue; + public static readonly Rgba32 DarkBlue = Color.DarkBlue; /// /// Represents a matching the W3C definition that has an hex value of #008B8B. /// - public static readonly Rgba32 DarkCyan = NamedColors.DarkCyan; + public static readonly Rgba32 DarkCyan = Color.DarkCyan; /// /// Represents a matching the W3C definition that has an hex value of #B8860B. /// - public static readonly Rgba32 DarkGoldenrod = NamedColors.DarkGoldenrod; + public static readonly Rgba32 DarkGoldenrod = Color.DarkGoldenrod; /// /// Represents a matching the W3C definition that has an hex value of #A9A9A9. /// - public static readonly Rgba32 DarkGray = NamedColors.DarkGray; + public static readonly Rgba32 DarkGray = Color.DarkGray; /// /// Represents a matching the W3C definition that has an hex value of #006400. /// - public static readonly Rgba32 DarkGreen = NamedColors.DarkGreen; + public static readonly Rgba32 DarkGreen = Color.DarkGreen; /// /// Represents a matching the W3C definition that has an hex value of #BDB76B. /// - public static readonly Rgba32 DarkKhaki = NamedColors.DarkKhaki; + public static readonly Rgba32 DarkKhaki = Color.DarkKhaki; /// /// Represents a matching the W3C definition that has an hex value of #8B008B. /// - public static readonly Rgba32 DarkMagenta = NamedColors.DarkMagenta; + public static readonly Rgba32 DarkMagenta = Color.DarkMagenta; /// /// Represents a matching the W3C definition that has an hex value of #556B2F. /// - public static readonly Rgba32 DarkOliveGreen = NamedColors.DarkOliveGreen; + public static readonly Rgba32 DarkOliveGreen = Color.DarkOliveGreen; /// /// Represents a matching the W3C definition that has an hex value of #FF8C00. /// - public static readonly Rgba32 DarkOrange = NamedColors.DarkOrange; + public static readonly Rgba32 DarkOrange = Color.DarkOrange; /// /// Represents a matching the W3C definition that has an hex value of #9932CC. /// - public static readonly Rgba32 DarkOrchid = NamedColors.DarkOrchid; + public static readonly Rgba32 DarkOrchid = Color.DarkOrchid; /// /// Represents a matching the W3C definition that has an hex value of #8B0000. /// - public static readonly Rgba32 DarkRed = NamedColors.DarkRed; + public static readonly Rgba32 DarkRed = Color.DarkRed; /// /// Represents a matching the W3C definition that has an hex value of #E9967A. /// - public static readonly Rgba32 DarkSalmon = NamedColors.DarkSalmon; + public static readonly Rgba32 DarkSalmon = Color.DarkSalmon; /// /// Represents a matching the W3C definition that has an hex value of #8FBC8B. /// - public static readonly Rgba32 DarkSeaGreen = NamedColors.DarkSeaGreen; + public static readonly Rgba32 DarkSeaGreen = Color.DarkSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #483D8B. /// - public static readonly Rgba32 DarkSlateBlue = NamedColors.DarkSlateBlue; + public static readonly Rgba32 DarkSlateBlue = Color.DarkSlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #2F4F4F. /// - public static readonly Rgba32 DarkSlateGray = NamedColors.DarkSlateGray; + public static readonly Rgba32 DarkSlateGray = Color.DarkSlateGray; /// /// Represents a matching the W3C definition that has an hex value of #00CED1. /// - public static readonly Rgba32 DarkTurquoise = NamedColors.DarkTurquoise; + public static readonly Rgba32 DarkTurquoise = Color.DarkTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #9400D3. /// - public static readonly Rgba32 DarkViolet = NamedColors.DarkViolet; + public static readonly Rgba32 DarkViolet = Color.DarkViolet; /// /// Represents a matching the W3C definition that has an hex value of #FF1493. /// - public static readonly Rgba32 DeepPink = NamedColors.DeepPink; + public static readonly Rgba32 DeepPink = Color.DeepPink; /// /// Represents a matching the W3C definition that has an hex value of #00BFFF. /// - public static readonly Rgba32 DeepSkyBlue = NamedColors.DeepSkyBlue; + public static readonly Rgba32 DeepSkyBlue = Color.DeepSkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #696969. /// - public static readonly Rgba32 DimGray = NamedColors.DimGray; + public static readonly Rgba32 DimGray = Color.DimGray; /// /// Represents a matching the W3C definition that has an hex value of #1E90FF. /// - public static readonly Rgba32 DodgerBlue = NamedColors.DodgerBlue; + public static readonly Rgba32 DodgerBlue = Color.DodgerBlue; /// /// Represents a matching the W3C definition that has an hex value of #B22222. /// - public static readonly Rgba32 Firebrick = NamedColors.Firebrick; + public static readonly Rgba32 Firebrick = Color.Firebrick; /// /// Represents a matching the W3C definition that has an hex value of #FFFAF0. /// - public static readonly Rgba32 FloralWhite = NamedColors.FloralWhite; + public static readonly Rgba32 FloralWhite = Color.FloralWhite; /// /// Represents a matching the W3C definition that has an hex value of #228B22. /// - public static readonly Rgba32 ForestGreen = NamedColors.ForestGreen; + public static readonly Rgba32 ForestGreen = Color.ForestGreen; /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly Rgba32 Fuchsia = NamedColors.Fuchsia; + public static readonly Rgba32 Fuchsia = Color.Fuchsia; /// /// Represents a matching the W3C definition that has an hex value of #DCDCDC. /// - public static readonly Rgba32 Gainsboro = NamedColors.Gainsboro; + public static readonly Rgba32 Gainsboro = Color.Gainsboro; /// /// Represents a matching the W3C definition that has an hex value of #F8F8FF. /// - public static readonly Rgba32 GhostWhite = NamedColors.GhostWhite; + public static readonly Rgba32 GhostWhite = Color.GhostWhite; /// /// Represents a matching the W3C definition that has an hex value of #FFD700. /// - public static readonly Rgba32 Gold = NamedColors.Gold; + public static readonly Rgba32 Gold = Color.Gold; /// /// Represents a matching the W3C definition that has an hex value of #DAA520. /// - public static readonly Rgba32 Goldenrod = NamedColors.Goldenrod; + public static readonly Rgba32 Goldenrod = Color.Goldenrod; /// /// Represents a matching the W3C definition that has an hex value of #808080. /// - public static readonly Rgba32 Gray = NamedColors.Gray; + public static readonly Rgba32 Gray = Color.Gray; /// /// Represents a matching the W3C definition that has an hex value of #008000. /// - public static readonly Rgba32 Green = NamedColors.Green; + public static readonly Rgba32 Green = Color.Green; /// /// Represents a matching the W3C definition that has an hex value of #ADFF2F. /// - public static readonly Rgba32 GreenYellow = NamedColors.GreenYellow; + public static readonly Rgba32 GreenYellow = Color.GreenYellow; /// /// Represents a matching the W3C definition that has an hex value of #F0FFF0. /// - public static readonly Rgba32 Honeydew = NamedColors.Honeydew; + public static readonly Rgba32 Honeydew = Color.Honeydew; /// /// Represents a matching the W3C definition that has an hex value of #FF69B4. /// - public static readonly Rgba32 HotPink = NamedColors.HotPink; + public static readonly Rgba32 HotPink = Color.HotPink; /// /// Represents a matching the W3C definition that has an hex value of #CD5C5C. /// - public static readonly Rgba32 IndianRed = NamedColors.IndianRed; + public static readonly Rgba32 IndianRed = Color.IndianRed; /// /// Represents a matching the W3C definition that has an hex value of #4B0082. /// - public static readonly Rgba32 Indigo = NamedColors.Indigo; + public static readonly Rgba32 Indigo = Color.Indigo; /// /// Represents a matching the W3C definition that has an hex value of #FFFFF0. /// - public static readonly Rgba32 Ivory = NamedColors.Ivory; + public static readonly Rgba32 Ivory = Color.Ivory; /// /// Represents a matching the W3C definition that has an hex value of #F0E68C. /// - public static readonly Rgba32 Khaki = NamedColors.Khaki; + public static readonly Rgba32 Khaki = Color.Khaki; /// /// Represents a matching the W3C definition that has an hex value of #E6E6FA. /// - public static readonly Rgba32 Lavender = NamedColors.Lavender; + public static readonly Rgba32 Lavender = Color.Lavender; /// /// Represents a matching the W3C definition that has an hex value of #FFF0F5. /// - public static readonly Rgba32 LavenderBlush = NamedColors.LavenderBlush; + public static readonly Rgba32 LavenderBlush = Color.LavenderBlush; /// /// Represents a matching the W3C definition that has an hex value of #7CFC00. /// - public static readonly Rgba32 LawnGreen = NamedColors.LawnGreen; + public static readonly Rgba32 LawnGreen = Color.LawnGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFFACD. /// - public static readonly Rgba32 LemonChiffon = NamedColors.LemonChiffon; + public static readonly Rgba32 LemonChiffon = Color.LemonChiffon; /// /// Represents a matching the W3C definition that has an hex value of #ADD8E6. /// - public static readonly Rgba32 LightBlue = NamedColors.LightBlue; + public static readonly Rgba32 LightBlue = Color.LightBlue; /// /// Represents a matching the W3C definition that has an hex value of #F08080. /// - public static readonly Rgba32 LightCoral = NamedColors.LightCoral; + public static readonly Rgba32 LightCoral = Color.LightCoral; /// /// Represents a matching the W3C definition that has an hex value of #E0FFFF. /// - public static readonly Rgba32 LightCyan = NamedColors.LightCyan; + public static readonly Rgba32 LightCyan = Color.LightCyan; /// /// Represents a matching the W3C definition that has an hex value of #FAFAD2. /// - public static readonly Rgba32 LightGoldenrodYellow = NamedColors.LightGoldenrodYellow; + public static readonly Rgba32 LightGoldenrodYellow = Color.LightGoldenrodYellow; /// /// Represents a matching the W3C definition that has an hex value of #D3D3D3. /// - public static readonly Rgba32 LightGray = NamedColors.LightGray; + public static readonly Rgba32 LightGray = Color.LightGray; /// /// Represents a matching the W3C definition that has an hex value of #90EE90. /// - public static readonly Rgba32 LightGreen = NamedColors.LightGreen; + public static readonly Rgba32 LightGreen = Color.LightGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFB6C1. /// - public static readonly Rgba32 LightPink = NamedColors.LightPink; + public static readonly Rgba32 LightPink = Color.LightPink; /// /// Represents a matching the W3C definition that has an hex value of #FFA07A. /// - public static readonly Rgba32 LightSalmon = NamedColors.LightSalmon; + public static readonly Rgba32 LightSalmon = Color.LightSalmon; /// /// Represents a matching the W3C definition that has an hex value of #20B2AA. /// - public static readonly Rgba32 LightSeaGreen = NamedColors.LightSeaGreen; + public static readonly Rgba32 LightSeaGreen = Color.LightSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #87CEFA. /// - public static readonly Rgba32 LightSkyBlue = NamedColors.LightSkyBlue; + public static readonly Rgba32 LightSkyBlue = Color.LightSkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #778899. /// - public static readonly Rgba32 LightSlateGray = NamedColors.LightSlateGray; + public static readonly Rgba32 LightSlateGray = Color.LightSlateGray; /// /// Represents a matching the W3C definition that has an hex value of #B0C4DE. /// - public static readonly Rgba32 LightSteelBlue = NamedColors.LightSteelBlue; + public static readonly Rgba32 LightSteelBlue = Color.LightSteelBlue; /// /// Represents a matching the W3C definition that has an hex value of #FFFFE0. /// - public static readonly Rgba32 LightYellow = NamedColors.LightYellow; + public static readonly Rgba32 LightYellow = Color.LightYellow; /// /// Represents a matching the W3C definition that has an hex value of #00FF00. /// - public static readonly Rgba32 Lime = NamedColors.Lime; + public static readonly Rgba32 Lime = Color.Lime; /// /// Represents a matching the W3C definition that has an hex value of #32CD32. /// - public static readonly Rgba32 LimeGreen = NamedColors.LimeGreen; + public static readonly Rgba32 LimeGreen = Color.LimeGreen; /// /// Represents a matching the W3C definition that has an hex value of #FAF0E6. /// - public static readonly Rgba32 Linen = NamedColors.Linen; + public static readonly Rgba32 Linen = Color.Linen; /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly Rgba32 Magenta = NamedColors.Magenta; + public static readonly Rgba32 Magenta = Color.Magenta; /// /// Represents a matching the W3C definition that has an hex value of #800000. /// - public static readonly Rgba32 Maroon = NamedColors.Maroon; + public static readonly Rgba32 Maroon = Color.Maroon; /// /// Represents a matching the W3C definition that has an hex value of #66CDAA. /// - public static readonly Rgba32 MediumAquamarine = NamedColors.MediumAquamarine; + public static readonly Rgba32 MediumAquamarine = Color.MediumAquamarine; /// /// Represents a matching the W3C definition that has an hex value of #0000CD. /// - public static readonly Rgba32 MediumBlue = NamedColors.MediumBlue; + public static readonly Rgba32 MediumBlue = Color.MediumBlue; /// /// Represents a matching the W3C definition that has an hex value of #BA55D3. /// - public static readonly Rgba32 MediumOrchid = NamedColors.MediumOrchid; + public static readonly Rgba32 MediumOrchid = Color.MediumOrchid; /// /// Represents a matching the W3C definition that has an hex value of #9370DB. /// - public static readonly Rgba32 MediumPurple = NamedColors.MediumPurple; + public static readonly Rgba32 MediumPurple = Color.MediumPurple; /// /// Represents a matching the W3C definition that has an hex value of #3CB371. /// - public static readonly Rgba32 MediumSeaGreen = NamedColors.MediumSeaGreen; + public static readonly Rgba32 MediumSeaGreen = Color.MediumSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #7B68EE. /// - public static readonly Rgba32 MediumSlateBlue = NamedColors.MediumSlateBlue; + public static readonly Rgba32 MediumSlateBlue = Color.MediumSlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #00FA9A. /// - public static readonly Rgba32 MediumSpringGreen = NamedColors.MediumSpringGreen; + public static readonly Rgba32 MediumSpringGreen = Color.MediumSpringGreen; /// /// Represents a matching the W3C definition that has an hex value of #48D1CC. /// - public static readonly Rgba32 MediumTurquoise = NamedColors.MediumTurquoise; + public static readonly Rgba32 MediumTurquoise = Color.MediumTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #C71585. /// - public static readonly Rgba32 MediumVioletRed = NamedColors.MediumVioletRed; + public static readonly Rgba32 MediumVioletRed = Color.MediumVioletRed; /// /// Represents a matching the W3C definition that has an hex value of #191970. /// - public static readonly Rgba32 MidnightBlue = NamedColors.MidnightBlue; + public static readonly Rgba32 MidnightBlue = Color.MidnightBlue; /// /// Represents a matching the W3C definition that has an hex value of #F5FFFA. /// - public static readonly Rgba32 MintCream = NamedColors.MintCream; + public static readonly Rgba32 MintCream = Color.MintCream; /// /// Represents a matching the W3C definition that has an hex value of #FFE4E1. /// - public static readonly Rgba32 MistyRose = NamedColors.MistyRose; + public static readonly Rgba32 MistyRose = Color.MistyRose; /// /// Represents a matching the W3C definition that has an hex value of #FFE4B5. /// - public static readonly Rgba32 Moccasin = NamedColors.Moccasin; + public static readonly Rgba32 Moccasin = Color.Moccasin; /// /// Represents a matching the W3C definition that has an hex value of #FFDEAD. /// - public static readonly Rgba32 NavajoWhite = NamedColors.NavajoWhite; + public static readonly Rgba32 NavajoWhite = Color.NavajoWhite; /// /// Represents a matching the W3C definition that has an hex value of #000080. /// - public static readonly Rgba32 Navy = NamedColors.Navy; + public static readonly Rgba32 Navy = Color.Navy; /// /// Represents a matching the W3C definition that has an hex value of #FDF5E6. /// - public static readonly Rgba32 OldLace = NamedColors.OldLace; + public static readonly Rgba32 OldLace = Color.OldLace; /// /// Represents a matching the W3C definition that has an hex value of #808000. /// - public static readonly Rgba32 Olive = NamedColors.Olive; + public static readonly Rgba32 Olive = Color.Olive; /// /// Represents a matching the W3C definition that has an hex value of #6B8E23. /// - public static readonly Rgba32 OliveDrab = NamedColors.OliveDrab; + public static readonly Rgba32 OliveDrab = Color.OliveDrab; /// /// Represents a matching the W3C definition that has an hex value of #FFA500. /// - public static readonly Rgba32 Orange = NamedColors.Orange; + public static readonly Rgba32 Orange = Color.Orange; /// /// Represents a matching the W3C definition that has an hex value of #FF4500. /// - public static readonly Rgba32 OrangeRed = NamedColors.OrangeRed; + public static readonly Rgba32 OrangeRed = Color.OrangeRed; /// /// Represents a matching the W3C definition that has an hex value of #DA70D6. /// - public static readonly Rgba32 Orchid = NamedColors.Orchid; + public static readonly Rgba32 Orchid = Color.Orchid; /// /// Represents a matching the W3C definition that has an hex value of #EEE8AA. /// - public static readonly Rgba32 PaleGoldenrod = NamedColors.PaleGoldenrod; + public static readonly Rgba32 PaleGoldenrod = Color.PaleGoldenrod; /// /// Represents a matching the W3C definition that has an hex value of #98FB98. /// - public static readonly Rgba32 PaleGreen = NamedColors.PaleGreen; + public static readonly Rgba32 PaleGreen = Color.PaleGreen; /// /// Represents a matching the W3C definition that has an hex value of #AFEEEE. /// - public static readonly Rgba32 PaleTurquoise = NamedColors.PaleTurquoise; + public static readonly Rgba32 PaleTurquoise = Color.PaleTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #DB7093. /// - public static readonly Rgba32 PaleVioletRed = NamedColors.PaleVioletRed; + public static readonly Rgba32 PaleVioletRed = Color.PaleVioletRed; /// /// Represents a matching the W3C definition that has an hex value of #FFEFD5. /// - public static readonly Rgba32 PapayaWhip = NamedColors.PapayaWhip; + public static readonly Rgba32 PapayaWhip = Color.PapayaWhip; /// /// Represents a matching the W3C definition that has an hex value of #FFDAB9. /// - public static readonly Rgba32 PeachPuff = NamedColors.PeachPuff; + public static readonly Rgba32 PeachPuff = Color.PeachPuff; /// /// Represents a matching the W3C definition that has an hex value of #CD853F. /// - public static readonly Rgba32 Peru = NamedColors.Peru; + public static readonly Rgba32 Peru = Color.Peru; /// /// Represents a matching the W3C definition that has an hex value of #FFC0CB. /// - public static readonly Rgba32 Pink = NamedColors.Pink; + public static readonly Rgba32 Pink = Color.Pink; /// /// Represents a matching the W3C definition that has an hex value of #DDA0DD. /// - public static readonly Rgba32 Plum = NamedColors.Plum; + public static readonly Rgba32 Plum = Color.Plum; /// /// Represents a matching the W3C definition that has an hex value of #B0E0E6. /// - public static readonly Rgba32 PowderBlue = NamedColors.PowderBlue; + public static readonly Rgba32 PowderBlue = Color.PowderBlue; /// /// Represents a matching the W3C definition that has an hex value of #800080. /// - public static readonly Rgba32 Purple = NamedColors.Purple; + public static readonly Rgba32 Purple = Color.Purple; /// /// Represents a matching the W3C definition that has an hex value of #663399. /// - public static readonly Rgba32 RebeccaPurple = NamedColors.RebeccaPurple; + public static readonly Rgba32 RebeccaPurple = Color.RebeccaPurple; /// /// Represents a matching the W3C definition that has an hex value of #FF0000. /// - public static readonly Rgba32 Red = NamedColors.Red; + public static readonly Rgba32 Red = Color.Red; /// /// Represents a matching the W3C definition that has an hex value of #BC8F8F. /// - public static readonly Rgba32 RosyBrown = NamedColors.RosyBrown; + public static readonly Rgba32 RosyBrown = Color.RosyBrown; /// /// Represents a matching the W3C definition that has an hex value of #4169E1. /// - public static readonly Rgba32 RoyalBlue = NamedColors.RoyalBlue; + public static readonly Rgba32 RoyalBlue = Color.RoyalBlue; /// /// Represents a matching the W3C definition that has an hex value of #8B4513. /// - public static readonly Rgba32 SaddleBrown = NamedColors.SaddleBrown; + public static readonly Rgba32 SaddleBrown = Color.SaddleBrown; /// /// Represents a matching the W3C definition that has an hex value of #FA8072. /// - public static readonly Rgba32 Salmon = NamedColors.Salmon; + public static readonly Rgba32 Salmon = Color.Salmon; /// /// Represents a matching the W3C definition that has an hex value of #F4A460. /// - public static readonly Rgba32 SandyBrown = NamedColors.SandyBrown; + public static readonly Rgba32 SandyBrown = Color.SandyBrown; /// /// Represents a matching the W3C definition that has an hex value of #2E8B57. /// - public static readonly Rgba32 SeaGreen = NamedColors.SeaGreen; + public static readonly Rgba32 SeaGreen = Color.SeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFF5EE. /// - public static readonly Rgba32 SeaShell = NamedColors.SeaShell; + public static readonly Rgba32 SeaShell = Color.SeaShell; /// /// Represents a matching the W3C definition that has an hex value of #A0522D. /// - public static readonly Rgba32 Sienna = NamedColors.Sienna; + public static readonly Rgba32 Sienna = Color.Sienna; /// /// Represents a matching the W3C definition that has an hex value of #C0C0C0. /// - public static readonly Rgba32 Silver = NamedColors.Silver; + public static readonly Rgba32 Silver = Color.Silver; /// /// Represents a matching the W3C definition that has an hex value of #87CEEB. /// - public static readonly Rgba32 SkyBlue = NamedColors.SkyBlue; + public static readonly Rgba32 SkyBlue = Color.SkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #6A5ACD. /// - public static readonly Rgba32 SlateBlue = NamedColors.SlateBlue; + public static readonly Rgba32 SlateBlue = Color.SlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #708090. /// - public static readonly Rgba32 SlateGray = NamedColors.SlateGray; + public static readonly Rgba32 SlateGray = Color.SlateGray; /// /// Represents a matching the W3C definition that has an hex value of #FFFAFA. /// - public static readonly Rgba32 Snow = NamedColors.Snow; + public static readonly Rgba32 Snow = Color.Snow; /// /// Represents a matching the W3C definition that has an hex value of #00FF7F. /// - public static readonly Rgba32 SpringGreen = NamedColors.SpringGreen; + public static readonly Rgba32 SpringGreen = Color.SpringGreen; /// /// Represents a matching the W3C definition that has an hex value of #4682B4. /// - public static readonly Rgba32 SteelBlue = NamedColors.SteelBlue; + public static readonly Rgba32 SteelBlue = Color.SteelBlue; /// /// Represents a matching the W3C definition that has an hex value of #D2B48C. /// - public static readonly Rgba32 Tan = NamedColors.Tan; + public static readonly Rgba32 Tan = Color.Tan; /// /// Represents a matching the W3C definition that has an hex value of #008080. /// - public static readonly Rgba32 Teal = NamedColors.Teal; + public static readonly Rgba32 Teal = Color.Teal; /// /// Represents a matching the W3C definition that has an hex value of #D8BFD8. /// - public static readonly Rgba32 Thistle = NamedColors.Thistle; + public static readonly Rgba32 Thistle = Color.Thistle; /// /// Represents a matching the W3C definition that has an hex value of #FF6347. /// - public static readonly Rgba32 Tomato = NamedColors.Tomato; + public static readonly Rgba32 Tomato = Color.Tomato; /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly Rgba32 Transparent = NamedColors.Transparent; + public static readonly Rgba32 Transparent = Color.Transparent; /// /// Represents a matching the W3C definition that has an hex value of #40E0D0. /// - public static readonly Rgba32 Turquoise = NamedColors.Turquoise; + public static readonly Rgba32 Turquoise = Color.Turquoise; /// /// Represents a matching the W3C definition that has an hex value of #EE82EE. /// - public static readonly Rgba32 Violet = NamedColors.Violet; + public static readonly Rgba32 Violet = Color.Violet; /// /// Represents a matching the W3C definition that has an hex value of #F5DEB3. /// - public static readonly Rgba32 Wheat = NamedColors.Wheat; + public static readonly Rgba32 Wheat = Color.Wheat; /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly Rgba32 White = NamedColors.White; + public static readonly Rgba32 White = Color.White; /// /// Represents a matching the W3C definition that has an hex value of #F5F5F5. /// - public static readonly Rgba32 WhiteSmoke = NamedColors.WhiteSmoke; + public static readonly Rgba32 WhiteSmoke = Color.WhiteSmoke; /// /// Represents a matching the W3C definition that has an hex value of #FFFF00. /// - public static readonly Rgba32 Yellow = NamedColors.Yellow; + public static readonly Rgba32 Yellow = Color.Yellow; /// /// Represents a matching the W3C definition that has an hex value of #9ACD32. /// - public static readonly Rgba32 YellowGreen = NamedColors.YellowGreen; + public static readonly Rgba32 YellowGreen = Color.YellowGreen; } } \ No newline at end of file From 51e23eb7d8bfcb0ea898e5348fe3b23caa5029e8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 14 May 2019 00:06:17 +0200 Subject: [PATCH 23/27] Remove NamedColors usages --- src/ImageSharp.Drawing/Processing/GradientBrushBase.cs | 4 +++- .../Attributes/WithSolidFilledImagesAttribute.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs index 6e1e0086da..39dbcb61a5 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs @@ -49,6 +49,8 @@ namespace SixLabors.ImageSharp.Processing internal abstract class GradientBrushApplicatorBase : BrushApplicator where TPixel : struct, IPixel { + private static readonly TPixel Transparent = Color.Transparent.ToPixel(); + private readonly ColorStop[] colorStops; private readonly GradientRepetitionMode repetitionMode; @@ -103,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing case GradientRepetitionMode.DontFill: if (positionOnCompleteGradient > 1 || positionOnCompleteGradient < 0) { - return NamedColors.Transparent; + return Transparent; } break; diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs index f95db45f71..190e80fbad 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs @@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Tests /// /// The width of the requested image /// The height of the requested image - /// The referenced color name (name of property in + /// The referenced color name (name of property in ). /// The requested pixel types /// Additional theory parameter values public WithSolidFilledImagesAttribute( @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Tests /// The member data to apply to theories /// The width of the requested image /// The height of the requested image - /// The referenced color name (name of property in + /// The referenced color name (name of property in ). /// The requested pixel types /// Additional theory parameter values public WithSolidFilledImagesAttribute( From 17f231101874904402fdab61089fa669f7493957 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 16 May 2019 23:38:28 +0200 Subject: [PATCH 24/27] drop unnecessary generic IImageProcessorContext usages --- .../Extensions/ProcessingExtensions.cs | 14 ++-- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 10 ++- .../Drawing/DrawTextOutline.cs | 5 +- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 10 +-- tests/ImageSharp.Tests/ImageOperationTests.cs | 39 ++++++----- .../Basic1ParameterConvolutionTests.cs | 6 +- .../Processors/Convolution/BoxBlurTest.cs | 4 +- .../Convolution/GaussianBlurTest.cs | 4 +- .../Convolution/GaussianSharpenTest.cs | 4 +- .../Processors/Transforms/ResizeTests.cs | 6 +- .../ImageProviders/TestImageProvider.cs | 2 +- .../TestUtilities/TestImageExtensions.cs | 69 ++++++++++--------- .../TestUtilities/TestUtils.cs | 14 ++-- 13 files changed, 99 insertions(+), 88 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index c72e8cfb77..e469af18b8 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image to mutate. /// The operation to perform on the source. - public static void Mutate(this Image source, Action> operation) + public static void Mutate(this Image source, Action operation) where TPixel : struct, IPixel { Guard.NotNull(operation, nameof(operation)); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image to mutate. /// The operations to perform on the source. - public static void Mutate(this Image source, params IImageProcessor[] operations) + public static void Mutate(this Image source, params IImageProcessor[] operations) where TPixel : struct, IPixel { Guard.NotNull(operations, nameof(operations)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to clone. /// The operation to perform on the clone. /// The new - public static Image Clone(this Image source, Action> operation) + public static Image Clone(this Image source, Action operation) where TPixel : struct, IPixel { Guard.NotNull(operation, nameof(operation)); @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to clone. /// The operations to perform on the clone. /// The new - public static Image Clone(this Image source, params IImageProcessor[] operations) + public static Image Clone(this Image source, params IImageProcessor[] operations) where TPixel : struct, IPixel { Guard.NotNull(operations, nameof(operations)); @@ -122,14 +122,12 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies the given collection against the context /// - /// The pixel format. /// The image processing context. /// The operations to perform on the source. /// The to allow chaining of operations. - public static IImageProcessingContext ApplyProcessors(this IImageProcessingContext source, params IImageProcessor[] operations) - where TPixel : struct, IPixel + public static IImageProcessingContext ApplyProcessors(this IImageProcessingContext source, params IImageProcessor[] operations) { - foreach (IImageProcessor p in operations) + foreach (IImageProcessor p in operations) { source = source.ApplyProcessor(p); } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 28f410e7d1..0982db3340 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -55,8 +55,14 @@ namespace SixLabors.ImageSharp.Benchmarks image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) - where TPixel : struct, IPixel + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, + TextGraphicsOptions options, + string text, + SixLabors.Fonts.Font font, + IBrush brush, + IPen pen, + SixLabors.Primitives.PointF location) { float dpiX = 72; float dpiY = 72; diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index 658590e2d4..c5c1ba5ac1 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -64,15 +64,14 @@ namespace SixLabors.ImageSharp.Benchmarks new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion( - IImageProcessingContext source, + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) - where TPixel : struct, IPixel { var style = new SixLabors.Fonts.RendererOptions(font, options.DpiX, options.DpiY, location) { diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index cf47202cc8..172e243729 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -91,12 +91,12 @@ namespace SixLabors.ImageSharp.Benchmarks } } - protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); + protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); } public class Resize_Bicubic_Rgba32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); } diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs index e694f0b644..b99ad64b24 100644 --- a/tests/ImageSharp.Tests/ImageOperationTests.cs +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -21,14 +21,21 @@ namespace SixLabors.ImageSharp.Tests { private readonly Image image; private readonly FakeImageOperationsProvider provider; - private readonly IImageProcessor processor; + private readonly IImageProcessor processorImplementation; + + private readonly IImageProcessor processorDefinition; public Configuration Configuration { get; private set; } public ImageOperationTests() { this.provider = new FakeImageOperationsProvider(); - this.processor = new Mock>().Object; + this.processorImplementation = new Mock>().Object; + + Mock processorMock = new Mock(); + processorMock.Setup(p => p.CreatePixelSpecificProcessor()).Returns(this.processorImplementation); + this.processorDefinition = processorMock.Object; + this.image = new Image(new Configuration() { ImageOperationsProvider = this.provider @@ -38,61 +45,61 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void MutateCallsImageOperationsProvider_Func_OriginalImage() { - this.image.Mutate(x => x.ApplyProcessor(this.processor)); + this.image.Mutate(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void MutateCallsImageOperationsProvider_ListOfProcessors_OriginalImage() { - this.image.Mutate(this.processor); + this.image.Mutate(this.processorDefinition); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_Func_WithDuplicateImage() { - Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_ListOfProcessors_WithDuplicateImage() { - Image returned = this.image.Clone(this.processor); + Image returned = this.image.Clone(this.processorDefinition); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_Func_NotOnOrigional() { - Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_ListOfProcessors_NotOnOrigional() { - Image returned = this.image.Clone(this.processor); + Image returned = this.image.Clone(this.processorDefinition); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void ApplyProcessors_ListOfProcessors_AppliesAllProcessorsToOperation() { var operations = new FakeImageOperationsProvider.FakeImageOperations(null, false); - operations.ApplyProcessors(this.processor); - Assert.Contains(this.processor, operations.Applied.Select(x => x.GenericProcessor)); + operations.ApplyProcessors(this.processorDefinition); + Assert.Contains(this.processorImplementation, operations.Applied.Select(x => x.GenericProcessor)); } public void Dispose() => this.image.Dispose(); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs index 1f939a281b..0a10d0755f 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs @@ -47,10 +47,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution ValidatorComparer); } - protected abstract void Apply(IImageProcessingContext ctx, int value) - where TPixel : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, int value); - protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) - where TPixel : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs index 923f9d6161..a7cf9360cf 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs @@ -9,9 +9,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class BoxBlurTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.BoxBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs index 6307a1c51d..68eb8c4f63 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs @@ -13,9 +13,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class GaussianBlurTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.GaussianBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs index 29a1643b0c..4b497309ee 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs @@ -12,9 +12,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class GaussianSharpenTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.GaussianSharpen(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 9bf9079d41..8ae298c51e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -322,11 +322,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } FormattableString testOutputDetails = $"{samplerName}-{destSizeInfo}"; - ctx.Apply( - img => img.DebugSave( - provider, - $"{testOutputDetails}-ORIGINAL", - appendPixelTypeToFileName: false)); + ctx.Resize((Size)newSize, sampler, false); return testOutputDetails; }, diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index 15fab9b2bf..8d493c7d43 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests /// /// Returns an instance to the test case with the necessary traits. /// - public Image GetImage(Action> operationsToApply) + public Image GetImage(Action operationsToApply) { Image img = this.GetImage(); img.Mutate(operationsToApply); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index e77b1974d3..8de3a347ba 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -9,10 +9,13 @@ using System.Numerics; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; using SixLabors.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; using Xunit; @@ -21,39 +24,11 @@ namespace SixLabors.ImageSharp.Tests public static class TestImageExtensions { /// - /// TODO: This should be a common processing method! The image.Opacity(val) multiplies the alpha channel! + /// TODO: Consider adding this private processor to the library /// - /// /// - public static void MakeOpaque(this IImageProcessingContext ctx) - where TPixel : struct, IPixel - { - MemoryAllocator memoryAllocator = ctx.MemoryAllocator; - - ctx.Apply( - img => - { - Configuration configuration = img.GetConfiguration(); - using (Buffer2D temp = memoryAllocator.Allocate2D(img.Width, img.Height)) - { - Span tempSpan = temp.GetSpan(); - foreach (ImageFrame frame in img.Frames) - { - Span pixelSpan = frame.GetPixelSpan(); - - PixelOperations.Instance.ToVector4(configuration, pixelSpan, tempSpan, PixelConversionModifiers.Scale); - - for (int i = 0; i < tempSpan.Length; i++) - { - ref Vector4 v = ref tempSpan[i]; - v.W = 1F; - } - - PixelOperations.Instance.FromVector4Destructive(configuration, tempSpan, pixelSpan, PixelConversionModifiers.Scale); - } - } - }); - } + public static void MakeOpaque(this IImageProcessingContext ctx) => + ctx.ApplyProcessor(new MakeOpaqueProcessor()); public static void DebugSave( this Image image, @@ -702,5 +677,37 @@ namespace SixLabors.ImageSharp.Tests return image; } + private class MakeOpaqueProcessor : IImageProcessor + { + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new MakeOpaqueProcessor(); + } + } + + private class MakeOpaqueProcessor : ImageProcessor + where TPixel : struct, IPixel + { + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + ParallelHelper.IterateRowsWithTempBuffer(sourceRectangle, configuration, + (rows, temp) => + { + Span tempSpan = temp.Span; + for (int y = rows.Min; y < rows.Max; y++) + { + var rowSpan = source.GetPixelRowSpan(y).Slice(sourceRectangle.Left, sourceRectangle.Width); + PixelOperations.Instance.ToVector4(configuration, rowSpan, tempSpan, PixelConversionModifiers.Scale); + for (int i = 0; i < tempSpan.Length; i++) + { + ref Vector4 v = ref tempSpan[i]; + v.W = 1F; + } + PixelOperations.Instance.FromVector4Destructive(configuration, tempSpan, rowSpan, PixelConversionModifiers.Scale); + } + }); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 5db0c08282..b56ce05171 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -165,7 +165,7 @@ namespace SixLabors.ImageSharp.Tests /// internal static void RunValidatingProcessorTest( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null, bool appendPixelTypeToFileName = true, @@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Tests internal static void RunValidatingProcessorTest( this TestImageProvider provider, - Func, FormattableString> processAndGetTestOutputDetails, + Func processAndGetTestOutputDetails, ImageComparer comparer = null, bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) @@ -241,7 +241,7 @@ namespace SixLabors.ImageSharp.Tests public static void RunValidatingProcessorTestOnWrappedMemoryImage( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null, string useReferenceOutputFrom = null, @@ -291,11 +291,11 @@ namespace SixLabors.ImageSharp.Tests } /// - /// Same as but with an additional parameter passed to 'process' + /// Same as 'RunValidatingProcessorTest{TPixel}' but with an additional parameter passed to 'process' /// internal static void RunRectangleConstrainedValidatingProcessorTest( this TestImageProvider provider, - Action, Rectangle> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null) where TPixel : struct, IPixel @@ -315,11 +315,11 @@ namespace SixLabors.ImageSharp.Tests } /// - /// Same as but without the 'CompareToReferenceOutput()' step. + /// Same as 'RunValidatingProcessorTest{TPixel}' but without the 'CompareToReferenceOutput()' step. /// internal static void RunProcessorTest( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null) where TPixel : struct, IPixel { From 7e57fce3076eb905f7ed6b3ddbf2dabf6cb68986 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 00:06:37 +0200 Subject: [PATCH 25/27] drop almost all usages of FileTestBase --- .../Binarization/BinaryDitherTests.cs | 19 ++++++++++--------- .../Binarization/BinaryThresholdTest.cs | 15 +++++++++++---- .../Processors/Transforms/PadTest.cs | 9 +++++++-- .../Processors/Transforms/RotateFlipTests.cs | 6 +++--- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs index 44fdfc7039..d3507ed4c4 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs @@ -12,7 +12,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { - public class BinaryDitherTests : FileTestBase + public class BinaryDitherTests { public static readonly string[] CommonTestImages = { @@ -40,14 +40,15 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { "Stucki", KnownDiffusers.Stucki }, }; + public const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24; private static IOrderedDither DefaultDitherer => KnownDitherers.BayerDither4x4; private static IErrorDiffuser DefaultErrorDiffuser => KnownDiffusers.Atkinson; [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), DefaultPixelType)] - [WithTestPatternImages(nameof(OrderedDitherers), 100, 100, DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(OrderedDitherers), 100, 100, PixelTypes.Rgba32)] public void BinaryDitherFilter_WorksWithAllDitherers(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -59,8 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), DefaultPixelType)] - [WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, PixelTypes.Rgba32)] public void DiffusionFilter_WorksWithAllErrorDiffusers(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { @@ -72,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.Bike, CommonNonDefaultPixelTypes)] + [WithFile(TestImages.Png.Bike, TestPixelTypes)] public void BinaryDitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -84,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.Bike, CommonNonDefaultPixelTypes)] + [WithFile(TestImages.Png.Bike, TestPixelTypes)] public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -96,7 +97,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] public void ApplyDitherFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { @@ -113,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] public void ApplyDiffusionFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs index 988c9125ba..4ae5d60513 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs @@ -11,17 +11,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { using SixLabors.ImageSharp.Processing; - public class BinaryThresholdTest : FileTestBase + public class BinaryThresholdTest { public static readonly TheoryData BinaryThresholdValues - = new TheoryData + = new TheoryData { .25F, .75F }; + + public static readonly string[] CommonTestImages = + { + TestImages.Png.CalliphoraPartial, TestImages.Png.Bike + }; + + public const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -33,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs index 6cce62d14e..750d67c32a 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs @@ -7,10 +7,15 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { - public class PadTest : FileTestBase + public class PadTest { + public static readonly string[] CommonTestImages = + { + TestImages.Png.CalliphoraPartial, TestImages.Png.Bike + }; + [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] public void ImageShouldPad(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs index d6376b1792..20e12cb7f9 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { using SixLabors.ImageSharp.Processing; - public class RotateFlipTests : FileTestBase + public class RotateFlipTests { public static readonly string[] FlipFiles = { TestImages.Bmp.F }; @@ -24,8 +24,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms }; [Theory] - [WithTestPatternImages(nameof(RotateFlipValues), 100, 50, DefaultPixelType)] - [WithTestPatternImages(nameof(RotateFlipValues), 50, 100, DefaultPixelType)] + [WithTestPatternImages(nameof(RotateFlipValues), 100, 50, PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(RotateFlipValues), 50, 100, PixelTypes.Rgba32)] public void RotateFlip(TestImageProvider provider, RotateMode rotateType, FlipMode flipType) where TPixel : struct, IPixel { From 3af895b55ef7ddd7d54d3999f5077bcb1fa0dab8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 00:29:06 +0200 Subject: [PATCH 26/27] fix tests --- .../Drawing/DrawImageTests.cs | 5 ++- tests/ImageSharp.Tests/ImageOperationTests.cs | 34 +++++++++++-------- tests/ImageSharp.Tests/Issues/Issue412.cs | 3 +- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index cb44651d6f..52821cf478 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -112,7 +112,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing image.Mutate(c => c.DrawImage(brushImage, 0.5f)); image.DebugSave(provider, appendSourceFileOrDescription: false); - image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + image.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + appendSourceFileOrDescription: false); } } diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs index b99ad64b24..30371f0008 100644 --- a/tests/ImageSharp.Tests/ImageOperationTests.cs +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -21,19 +21,13 @@ namespace SixLabors.ImageSharp.Tests { private readonly Image image; private readonly FakeImageOperationsProvider provider; - private readonly IImageProcessor processorImplementation; - private readonly IImageProcessor processorDefinition; - public Configuration Configuration { get; private set; } - public ImageOperationTests() { this.provider = new FakeImageOperationsProvider(); - this.processorImplementation = new Mock>().Object; - + Mock processorMock = new Mock(); - processorMock.Setup(p => p.CreatePixelSpecificProcessor()).Returns(this.processorImplementation); this.processorDefinition = processorMock.Object; this.image = new Image(new Configuration() @@ -48,7 +42,9 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -57,7 +53,9 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(this.processorDefinition); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -66,7 +64,9 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(returned).Select(x => x.NonGenericProcessor)); } [Fact] @@ -75,7 +75,9 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(this.processorDefinition); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(returned).Select(x => x.NonGenericProcessor)); } [Fact] @@ -83,7 +85,9 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -91,7 +95,9 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(this.processorDefinition); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -99,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests { var operations = new FakeImageOperationsProvider.FakeImageOperations(null, false); operations.ApplyProcessors(this.processorDefinition); - Assert.Contains(this.processorImplementation, operations.Applied.Select(x => x.GenericProcessor)); + Assert.Contains(this.processorDefinition, operations.Applied.Select(x => x.NonGenericProcessor)); } public void Dispose() => this.image.Dispose(); diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs index f22d3a85cf..7b2cfd81c6 100644 --- a/tests/ImageSharp.Tests/Issues/Issue412.cs +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -46,8 +46,9 @@ namespace SixLabors.ImageSharp.Tests.Issues { for (var x = 0; x < 40; x++) { + TPixel red = Color.Red.ToPixel(); - Assert.True(Color.Red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); + Assert.True(red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); } } } From a36aa55a59a116aaac50b280852dc6d5b755b5a2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 01:01:20 +0200 Subject: [PATCH 27/27] re-enable target frameworks --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 +-- src/ImageSharp/ImageSharp.csproj | 3 +-- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 722ef33ff0..f9181b45da 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 1b213c26dc..832a6ce3f9 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index efdf89964c..0b727f30ce 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,7 +1,6 @@  - - netcoreapp2.1 + netcoreapp2.1;net462;net472 True latest full