diff --git a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs index 1ec27d762..2d69e0ad5 100644 --- a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs +++ b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs @@ -12,113 +12,135 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { + [GroupOutput("Drawing/GradientBrushes")] public class FillEllipticGradientBrushTests : FileTestBase { - [Fact] - public void EllipticGradientBrushWithEqualColorsAndReturnsUnicolorImage() + [Theory] + [WithBlankImages(10, 10, PixelTypes.Rgba32)] + public void EllipticGradientBrushWithEqualColorsAndReturnsUnicolorImage( + TestImageProvider provider) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Fill", "EllipticGradientBrush"); - using (var image = new Image(10, 10)) + TPixel red = NamedColors.Red; + + using (Image image = provider.GetImage()) { - EllipticGradientBrush unicolorLinearGradientBrush = - new EllipticGradientBrush( + EllipticGradientBrush unicolorLinearGradientBrush = + new EllipticGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), 1.0f, GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/UnicolorCircleGradient.png"); + image.DebugSave(provider); - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.Red, sourcePixels[0, 0]); - Assert.Equal(Rgba32.Red, sourcePixels[9, 9]); - Assert.Equal(Rgba32.Red, sourcePixels[5, 5]); - Assert.Equal(Rgba32.Red, sourcePixels[3, 8]); + Assert.Equal(red, sourcePixels[0, 0]); + Assert.Equal(red, sourcePixels[9, 9]); + Assert.Equal(red, sourcePixels[5, 5]); + Assert.Equal(red, sourcePixels[3, 8]); } + + image.CompareToReferenceOutput(provider); } } [Theory] - [InlineData(0.1)] - [InlineData(0.4)] - [InlineData(0.8)] - [InlineData(1.0)] - [InlineData(1.2)] - [InlineData(1.6)] - [InlineData(2.0)] - public void EllipticGradientBrushProducesAxisParallelEllipsesWithDifferentRatio( + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.1)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.4)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.8)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.0)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.2)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.6)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 2.0)] + public void EllipticGradientBrushProducesAxisParallelEllipsesWithDifferentRatio( + TestImageProvider provider, float ratio) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Fill", "EllipticGradientBrush"); - using (var image = new Image(1000, 1000)) + TPixel yellow = NamedColors.Yellow; + TPixel red = NamedColors.Red; + TPixel black = NamedColors.Black; + + using (var image = provider.GetImage()) { - EllipticGradientBrush unicolorLinearGradientBrush = - new EllipticGradientBrush( - new SixLabors.Primitives.Point(500, 500), - new SixLabors.Primitives.Point(500, 750), + EllipticGradientBrush unicolorLinearGradientBrush = + new EllipticGradientBrush( + new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2), + new SixLabors.Primitives.Point(image.Width / 2, (image.Width * 3) / 2), ratio, GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Yellow), - new ColorStop(1, Rgba32.Red), - new ColorStop(1, Rgba32.Black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/Ellipsis{ratio}.png"); + image.DebugSave(provider, ratio); + image.CompareToReferenceOutput(provider, ratio); } } [Theory] - [InlineData(0.1, 0)] - [InlineData(0.4, 0)] - [InlineData(0.8, 0)] - [InlineData(1.0, 0)] - - [InlineData(0.1, 45)] - [InlineData(0.4, 45)] - [InlineData(0.8, 45)] - [InlineData(1.0, 45)] - - [InlineData(0.1, 90)] - [InlineData(0.4, 90)] - [InlineData(0.8, 90)] - [InlineData(1.0, 90)] - - [InlineData(0.1, 30)] - [InlineData(0.4, 30)] - [InlineData(0.8, 30)] - [InlineData(1.0, 30)] - public void EllipticGradientBrushProducesRotatedEllipsesWithDifferentRatio( + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.1, 0)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.4, 0)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.8, 0)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.0, 0)] + + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.1, 45)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.4, 45)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.8, 45)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.0, 45)] + + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.1, 90)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.4, 90)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.8, 90)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.0, 90)] + + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.1, 30)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.4, 30)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 0.8, 30)] + [WithBlankImages(1000, 1000, PixelTypes.Rgba32, 1.0, 30)] + public void EllipticGradientBrushProducesRotatedEllipsesWithDifferentRatio( + TestImageProvider provider, float ratio, float rotationInDegree) + where TPixel: struct, IPixel { - var center = new SixLabors.Primitives.Point(500, 500); + string variant = $"{ratio}at{rotationInDegree}°"; + + using (var image = provider.GetImage()) + { + TPixel yellow = NamedColors.Yellow; + TPixel red = NamedColors.Red; + TPixel black = NamedColors.Black; - var rotation = (Math.PI * rotationInDegree) / 180.0; - var cos = Math.Cos(rotation); - var sin = Math.Sin(rotation); + var center = new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2); - int axisX = (int)((center.X * cos) - (center.Y * sin)); - int axisY = (int)((center.X * sin) + (center.Y * cos)); + var rotation = (Math.PI * rotationInDegree) / 180.0; + var cos = Math.Cos(rotation); + var sin = Math.Sin(rotation); - string path = TestEnvironment.CreateOutputDirectory("Fill", "EllipticGradientBrush"); - using (var image = new Image(1000, 1000)) - { - EllipticGradientBrush unicolorLinearGradientBrush = - new EllipticGradientBrush( + int axisX = (int)((center.X * cos) - (center.Y * sin)); + int axisY = (int)((center.X * sin) + (center.Y * cos)); + + + EllipticGradientBrush unicolorLinearGradientBrush = + new EllipticGradientBrush( center, new SixLabors.Primitives.Point(axisX, axisY), ratio, GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Yellow), - new ColorStop(1, Rgba32.Red), - new ColorStop(1, Rgba32.Black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/Ellipsis{ratio}_rot{rotationInDegree}°.png"); + image.DebugSave(provider, variant); + image.CompareToReferenceOutput(provider, variant); } } } diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index d080896a0..14ec69e82 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -1,7 +1,10 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; +using System.Globalization; using System.Linq; +using System.Text; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -12,305 +15,364 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { + [GroupOutput("Drawing/GradientBrushes")] public class FillLinearGradientBrushTests : FileTestBase { - [Fact] - public void LinearGradientBrushWithEqualColorsReturnsUnicolorImage() + [Theory] + [WithBlankImages(10, 10, PixelTypes.Rgba32)] + public void WithEqualColorsReturnsUnicolorImage( + TestImageProvider provider) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(10, 10)) + TPixel red = NamedColors.Red; + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/UnicolorGradient.png"); - - using (PixelAccessor sourcePixels = image.Lock()) - { - Assert.Equal(Rgba32.Red, sourcePixels[0, 0]); - Assert.Equal(Rgba32.Red, sourcePixels[9, 9]); - Assert.Equal(Rgba32.Red, sourcePixels[5, 5]); - Assert.Equal(Rgba32.Red, sourcePixels[3, 8]); - } + image.DebugSave(provider); + image.CompareToReferenceOutput(provider); } } - [Fact] - public void HorizontalLinearGradientBrushReturnsUnicolorColumns() + [Theory] + [WithBlankImages(500, 10, PixelTypes.Rgba32)] + public void HorizontalReturnsUnicolorColumns( + TestImageProvider provider) + where TPixel : struct, IPixel { - int width = 500; - int height = 10; - int lastColumnIndex = width - 1; - - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(width, height)) + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + int lastColumnIndex = image.Width - 1; + TPixel red = NamedColors.Red; + TPixel yellow = NamedColors.Yellow; + + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(500, 0), + new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/horizontalRedToYellow.png"); + image.DebugSave(provider); - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { - Rgba32 columnColor0 = sourcePixels[0, 0]; - Rgba32 columnColor23 = sourcePixels[23, 0]; - Rgba32 columnColor42 = sourcePixels[42, 0]; - Rgba32 columnColor333 = sourcePixels[333, 0]; + TPixel columnColor0 = sourcePixels[0, 0]; + TPixel columnColor23 = sourcePixels[23, 0]; + TPixel columnColor42 = sourcePixels[42, 0]; + TPixel columnColor333 = sourcePixels[333, 0]; - Rgba32 lastColumnColor = sourcePixels[lastColumnIndex, 0]; + TPixel lastColumnColor = sourcePixels[lastColumnIndex, 0]; - for (int i = 0; i < height; i++) + for (int i = 0; i < image.Height; i++) { // check first and last column: Assert.Equal(columnColor0, sourcePixels[0, i]); Assert.Equal(lastColumnColor, sourcePixels[lastColumnIndex, i]); // check the random colors: - Assert.True(columnColor23 == sourcePixels[23, i], $"at {i}"); + Assert.True(columnColor23.Equals(sourcePixels[23, i]), $"at {i}"); Assert.Equal(columnColor42, sourcePixels[42, i]); Assert.Equal(columnColor333, sourcePixels[333, i]); } } + + image.CompareToReferenceOutput(provider); } } [Theory] - [InlineData(GradientRepetitionMode.DontFill)] - [InlineData(GradientRepetitionMode.None)] - [InlineData(GradientRepetitionMode.Repeat)] - [InlineData(GradientRepetitionMode.Reflect)] - public void HorizontalLinearGradientBrushWithDifferentRepetitionModesCreatesCorrectImages( + [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.DontFill)] + [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.None)] + [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.Repeat)] + [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.Reflect)] + public void HorizontalGradientWithRepMode( + TestImageProvider provider, GradientRepetitionMode repetitionMode) + where TPixel : struct, IPixel { - int width = 500; - int height = 10; - int lastColumnIndex = width - 1; - - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(width, height)) + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + int lastColumnIndex = image.Width - 1; + + TPixel red = NamedColors.Red; + TPixel yellow = NamedColors.Yellow; + + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(50, 0), + new SixLabors.Primitives.Point(image.Width / 10, 0), repetitionMode, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/horizontalRedToYellow_{repetitionMode}.png"); + image.DebugSave(provider, repetitionMode); - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { - Rgba32 columnColor0 = sourcePixels[0, 0]; - Rgba32 columnColor23 = sourcePixels[23, 0]; - Rgba32 columnColor42 = sourcePixels[42, 0]; - Rgba32 columnColor333 = sourcePixels[333, 0]; + TPixel columnColor0 = sourcePixels[0, 0]; + TPixel columnColor23 = sourcePixels[23, 0]; + TPixel columnColor42 = sourcePixels[42, 0]; + TPixel columnColor333 = sourcePixels[333, 0]; - Rgba32 lastColumnColor = sourcePixels[lastColumnIndex, 0]; + TPixel lastColumnColor = sourcePixels[lastColumnIndex, 0]; - for (int i = 0; i < height; i++) + for (int i = 0; i < image.Height; i++) { // check first and last column: Assert.Equal(columnColor0, sourcePixels[0, i]); Assert.Equal(lastColumnColor, sourcePixels[lastColumnIndex, i]); // check the random colors: - Assert.True(columnColor23 == sourcePixels[23, i], $"at {i}"); + Assert.True(columnColor23.Equals(sourcePixels[23, i]), $"at {i}"); Assert.Equal(columnColor42, sourcePixels[42, i]); Assert.Equal(columnColor333, sourcePixels[333, i]); } } + + image.CompareToReferenceOutput(provider, repetitionMode); } } [Theory] - [InlineData(new[] { 0.5f })] - [InlineData(new[] { 0.2f, 0.4f, 0.6f, 0.8f })] - [InlineData(new[] { 0.1f, 0.3f, 0.6f })] - public void LinearGradientsWithDoubledStopsProduceDashedPatterns( + [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.5f })] + [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.2f, 0.4f, 0.6f, 0.8f })] + [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.1f, 0.3f, 0.6f })] + public void WithDoubledStopsProduceDashedPatterns( + TestImageProvider provider, float[] pattern) + where TPixel : struct, IPixel { - int width = 200; - int height = 10; + string variant = string.Join(",", pattern.Select(i => i.ToString(CultureInfo.InvariantCulture))); // ensure the input data is valid Assert.True(pattern.Length > 0); + TPixel black = NamedColors.Black; + TPixel white = NamedColors.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, Rgba32.Black), 1) + ColorStop[] colorStops = + Enumerable.Repeat(new ColorStop(0, black), 1) .Concat( pattern .SelectMany((f, index) => new[] { - new ColorStop(f, index % 2 == 0 ? Rgba32.Black : Rgba32.White), - new ColorStop(f, index % 2 == 0 ? Rgba32.White : Rgba32.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 ? Rgba32.Black : Rgba32.White), 1)) + .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) .ToArray(); - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(width, height)) + using (Image image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(width, 0), + new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, colorStops); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/blackAndWhite{pattern[0]}.png"); + image.DebugSave(provider, variant); - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { // the result must be a black and white pattern, no other color should occur: Assert.All( - Enumerable.Range(0, width).Select(i => sourcePixels[i, 0]), - color => Assert.True(color == Rgba32.Black || color == Rgba32.White)); + Enumerable.Range(0, image.Width).Select(i => sourcePixels[i, 0]), + color => Assert.True(color.Equals(black) || color.Equals(white))); } + + image.CompareToReferenceOutput(provider, variant); } } - [Fact] - public void VerticalLinearGradientBrushReturnsUnicolorColumns() + [Theory] + [WithBlankImages(10, 500, PixelTypes.Rgba32)] + public void VerticalReturnsUnicolorColumns( + TestImageProvider provider) + where TPixel : struct, IPixel { - int width = 10; - int height = 500; - int lastRowIndex = height - 1; - - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(width, height)) + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + int lastRowIndex = image.Height - 1; + + TPixel red = NamedColors.Red; + TPixel yellow = NamedColors.Yellow; + + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(0, 500), + new SixLabors.Primitives.Point(0, image.Height), GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/verticalRedToYellow.png"); + image.DebugSave(provider); + + Random random = new Random(); - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { - Rgba32 firstRowColor = sourcePixels[0, 0]; + TPixel firstRowColor = sourcePixels[0, 0]; - Rgba32 columnColor23 = sourcePixels[0, 23]; - Rgba32 columnColor42 = sourcePixels[0, 42]; - Rgba32 columnColor333 = sourcePixels[0, 333]; + int columnA = random.Next(0, image.Height); + int columnB = random.Next(0, image.Height); + int columnC = random.Next(0, image.Height); + TPixel columnColorA = sourcePixels[0, columnA]; + TPixel columnColorB = sourcePixels[0, columnB]; + TPixel columnColorC = sourcePixels[0, columnC]; - Rgba32 lastRowColor = sourcePixels[0, lastRowIndex]; + TPixel lastRowColor = sourcePixels[0, lastRowIndex]; - for (int i = 0; i < width; i++) + for (int i = 0; i < image.Width; i++) { // check first and last column, these are known: Assert.Equal(firstRowColor, sourcePixels[i, 0]); Assert.Equal(lastRowColor, sourcePixels[i, lastRowIndex]); // check the random colors: - Assert.Equal(columnColor23, sourcePixels[i, 23]); - Assert.Equal(columnColor42, sourcePixels[i, 42]); - Assert.Equal(columnColor333, sourcePixels[i, 333]); + Assert.Equal(columnColorA, sourcePixels[i, columnA]); + Assert.Equal(columnColorB, sourcePixels[i, columnB]); + Assert.Equal(columnColorC, sourcePixels[i, columnC]); } } + + image.CompareToReferenceOutput(provider); } } - [Theory] - [InlineData(0, 0, 499, 499)] - [InlineData(0, 499, 499, 0)] - [InlineData(499, 499, 0, 0)] - [InlineData(499, 0, 0, 499)] - public void DiagonalLinearGradientBrushReturnsUnicolorColumns( - int startX, int startY, int endX, int endY) + public enum ImageCorner { - int size = 500; + TopLeft = 0, + TopRight = 1, + BottomLeft = 2, + BottomRight = 3 + } - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(size, size)) + [Theory] + [WithBlankImages(500, 500, PixelTypes.Rgba32, ImageCorner.TopLeft)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, ImageCorner.TopRight)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, ImageCorner.BottomLeft)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, ImageCorner.BottomRight)] + public void DiagonalReturnsCorrectImages( + TestImageProvider provider, + ImageCorner startCorner) + where TPixel : struct, IPixel + { + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + Assert.True(image.Height == image.Width, "For the math check block at the end the image must be squared, but it is not."); + + int startX = (int)startCorner % 2 == 0 ? 0 : image.Width - 1; + int startY = startCorner > ImageCorner.TopRight ? 0 : image.Height - 1; + int endX = image.Height - startX - 1; + int endY = image.Width - startY - 1; + + TPixel red = NamedColors.Red; + TPixel yellow = NamedColors.Yellow; + + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/diagonalRedToYellowFrom{startX}_{startY}.png"); + image.DebugSave(provider, startCorner); + + int verticalSign = startY == 0 ? 1 : -1; + int horizontalSign = startX == 0 ? 1 : -1; - using (PixelAccessor sourcePixels = image.Lock()) + using (PixelAccessor sourcePixels = image.Lock()) { // check first and last pixel, these are known: - Assert.Equal(Rgba32.Red, sourcePixels[startX, startY]); - Assert.Equal(Rgba32.Yellow, sourcePixels[endX, endY]); + Assert.Equal(red, sourcePixels[startX, startY]); + Assert.Equal(yellow, sourcePixels[endX, endY]); - for (int i = 0; i < size; i++) + for (int i = 0; i < image.Height; i++) { // it's diagonal, so for any (a, a) on the gradient line, for all (a-x, b+x) - +/- depending on the diagonal direction - must be the same color) + TPixel colorOnDiagonal = sourcePixels[i, i]; + int orthoCount = 0; + for (int offset = -orthoCount; offset < orthoCount; offset++) + { + Assert.Equal(colorOnDiagonal, sourcePixels[i + horizontalSign * offset, i + verticalSign * offset]); + } } } + + image.CompareToReferenceOutput(provider, startCorner); } } [Theory] - [InlineData("a", 0, 0, 499, 499, new[] { 0f, .2f, .5f, .9f }, new[] { 0, 0, 1, 1 })] - [InlineData("b", 0, 499, 499, 0, new[] { 0f, 0.2f, 0.5f, 0.9f }, new[] { 0, 1, 2, 3 })] - [InlineData("c", 499, 499, 0, 0, new[] { 0f, 0.7f, 0.8f, 0.9f}, new[] { 0, 1, 2, 0 })] - [InlineData("d", 0, 0, 499, 499, new[] { 0f, .5f, 1f}, new[]{0, 1, 3})] - public void ArbitraryLinearGradientsProduceImagesVisualCheckOnly( - string filenameSuffix, + [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .2f, .5f, .9f }, new[] { 0, 0, 1, 1 })] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 499, 499, 0, new[] { 0f, 0.2f, 0.5f, 0.9f }, new[] { 0, 1, 2, 3 })] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 499, 499, 0, 0, new[] { 0f, 0.7f, 0.8f, 0.9f}, new[] { 0, 1, 2, 0 })] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .5f, 1f}, new[]{0, 1, 3})] + // TODO: add some more tests with arbitrary gradient orders! + public void ArbitraryGradients( + TestImageProvider provider, int startX, int startY, int endX, int endY, float[] stopPositions, int[] stopColorCodes) + where TPixel : struct, IPixel { - var colors = new Rgba32[] + var colors = new [] { - Rgba32.Navy, - Rgba32.LightGreen, - Rgba32.Yellow, - Rgba32.Red + NamedColors.Navy, + NamedColors.LightGreen, + NamedColors.Yellow, + NamedColors.Red }; - var colorStops = new ColorStop[stopPositions.Length]; + StringBuilder coloringVariant = new StringBuilder(); + var colorStops = new ColorStop[stopPositions.Length]; for (int i = 0; i < stopPositions.Length; i++) { - colorStops[i] = new ColorStop( - stopPositions[i], - colors[stopColorCodes[i]]); + TPixel color = colors[stopColorCodes[i % colors.Length]]; + float position = stopPositions[i]; + + colorStops[i] = new ColorStop( + position, + color); + coloringVariant.AppendFormat( + CultureInfo.InvariantCulture, + "{0}@{1};", + color, + position); } - int size = 500; + string variant = $"{startX},{startY}to{endX},{endY};[{coloringVariant}]"; - string path = TestEnvironment.CreateOutputDirectory("Fill", "LinearGradientBrush"); - using (var image = new Image(size, size)) + using (var image = provider.GetImage()) { - LinearGradientBrush unicolorLinearGradientBrush = - new LinearGradientBrush( + LinearGradientBrush unicolorLinearGradientBrush = + new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, colorStops); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.Save($"{path}/arbitraryGradient_{filenameSuffix}.png"); + image.DebugSave(provider, variant); + image.CompareToReferenceOutput(provider, variant); } } } diff --git a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs index 7229e7041..9fa2c65fa 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs @@ -9,80 +9,56 @@ namespace SixLabors.ImageSharp.Tests.Drawing { public class FillRadialGradientBrushTests : FileTestBase { - [Fact] - public void RadialGradientBrushWithEqualColorsReturnsUnicolorImage() + [Theory] + [WithBlankImages(200, 200, PixelTypes.Rgba32)] + public void RadialGradientBrushWithEqualColorsReturnsUnicolorImage( + TestImageProvider provider) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Fill", "RadialGradientBrush"); - using (var image = new Image(200, 200)) + using (var image = provider.GetImage()) { - RadialGradientBrush unicolorRadialGradientBrush = - new RadialGradientBrush( + TPixel red = NamedColors.Red; + + RadialGradientBrush unicolorRadialGradientBrush = + new RadialGradientBrush( new SixLabors.Primitives.Point(0, 0), 100, GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorRadialGradientBrush)); - image.Save($"{path}/UnicolorGradient.png"); + image.DebugSave(provider); - using (PixelAccessor sourcePixels = image.Lock()) - { - Assert.Equal(Rgba32.Red, sourcePixels[0, 0]); - Assert.Equal(Rgba32.Red, sourcePixels[9, 9]); - Assert.Equal(Rgba32.Red, sourcePixels[5, 5]); - Assert.Equal(Rgba32.Red, sourcePixels[3, 8]); - } + image.CompareToReferenceOutput(provider); } } [Theory] - [InlineData(250, 250)] - [InlineData(0, 0)] - [InlineData(250, 0)] - [InlineData(0, 250)] - [InlineData(-100, 250)] - public void RadialGradientBrushWithDifferentCentersReturnsImage( + [WithBlankImages(500, 500, PixelTypes.Rgba32, 250, 250)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 250, 0)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 250)] + [WithBlankImages(500, 500, PixelTypes.Rgba32, -100, 250)] + public void RadialGradientBrushWithDifferentCentersReturnsImage( + TestImageProvider provider, int centerX, int centerY) + where TPixel : struct, IPixel { - int width = 500; - - string path = TestEnvironment.CreateOutputDirectory("Fill", "RadialGradientBrush"); - using (var image = new Image(width, width)) + using (var image = provider.GetImage()) { - RadialGradientBrush brush = - new RadialGradientBrush( + RadialGradientBrush brush = + new RadialGradientBrush( new SixLabors.Primitives.Point(centerX, centerY), - width / 2f, + image.Width / 2f, GradientRepetitionMode.None, - new ColorStop(0, Rgba32.Red), - new ColorStop(1, Rgba32.Yellow)); + new ColorStop(0, NamedColors.Red), + new ColorStop(1, NamedColors.Yellow)); image.Mutate(x => x.Fill(brush)); - image.Save($"{path}/CenterAt{centerX}_{centerY}.png"); - - // using (PixelAccessor sourcePixels = image.Lock()) - // { - // Rgba32 columnColor0 = sourcePixels[0, 0]; - // Rgba32 columnColor23 = sourcePixels[23, 0]; - // Rgba32 columnColor42 = sourcePixels[42, 0]; - // Rgba32 columnColor333 = sourcePixels[333, 0]; - // - // Rgba32 lastColumnColor = sourcePixels[lastColumnIndex, 0]; - // - // for (int i = 0; i < width; i++) - // { - // // check first and last column: - // Assert.Equal(columnColor0, sourcePixels[0, i]); - // Assert.Equal(lastColumnColor, sourcePixels[lastColumnIndex, i]); - // - // // check the random colors: - // Assert.True(columnColor23 == sourcePixels[23, i], $"at {i}"); - // Assert.Equal(columnColor42, sourcePixels[42, i]); - // Assert.Equal(columnColor333, sourcePixels[333, i]); - // } - // } + image.DebugSave(provider); + image.CompareToReferenceOutput(provider); } } }