From c8b1b77d09562fa3f59b5506638fe53addbdbf1c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 12 Dec 2017 12:10:15 +0100 Subject: [PATCH] failing test for edge artifacts, minimalistic RotateTests, better Rgba32.ToString() --- src/ImageSharp/PixelFormats/Rgb24.cs | 6 ++ src/ImageSharp/PixelFormats/Rgba32.cs | 2 +- .../Processors/Transforms/RotateTests.cs | 62 ++------------- .../Processing/Transforms/TransformTests.cs | 79 +++++++++++++++---- 4 files changed, 77 insertions(+), 72 deletions(-) diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs index 5a12cff20..d867d9065 100644 --- a/src/ImageSharp/PixelFormats/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/Rgb24.cs @@ -126,5 +126,11 @@ namespace SixLabors.ImageSharp.PixelFormats dest.B = this.B; dest.A = 255; } + + /// + public override string ToString() + { + return $"({this.R},{this.G},{this.B})"; + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 51647fc1f..83a35f189 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -364,7 +364,7 @@ namespace SixLabors.ImageSharp /// A string representation of the packed vector. public override string ToString() { - return this.ToVector4().ToString(); + return $"({this.R},{this.G},{this.B},{this.A})"; } /// diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs index ca29009bc..b5220ea94 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs @@ -13,11 +13,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public class RotateTests : FileTestBase { - public static readonly TheoryData RotateFloatValues + public static readonly TheoryData RotateAngles = new TheoryData { - 170, - -170 + 50, -50, 170, -170 }; public static readonly TheoryData RotateEnumValues @@ -28,31 +27,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms RotateType.Rotate180, RotateType.Rotate270 }; - - public static readonly TheoryData ResamplerNames - = new TheoryData - { - nameof(KnownResamplers.Bicubic), - nameof(KnownResamplers.Box), - nameof(KnownResamplers.CatmullRom), - nameof(KnownResamplers.Hermite), - nameof(KnownResamplers.Lanczos2), - nameof(KnownResamplers.Lanczos3), - nameof(KnownResamplers.Lanczos5), - nameof(KnownResamplers.Lanczos8), - nameof(KnownResamplers.MitchellNetravali), - nameof(KnownResamplers.NearestNeighbor), - nameof(KnownResamplers.Robidoux), - nameof(KnownResamplers.RobidouxSharp), - nameof(KnownResamplers.Spline), - nameof(KnownResamplers.Triangle), - nameof(KnownResamplers.Welch), - }; - + [Theory] - [WithTestPatternImages(nameof(RotateFloatValues), 100, 50, DefaultPixelType)] - [WithTestPatternImages(nameof(RotateFloatValues), 50, 100, DefaultPixelType)] - public void Rotate(TestImageProvider provider, float value) + [WithTestPatternImages(nameof(RotateAngles), 100, 50, DefaultPixelType)] + [WithTestPatternImages(nameof(RotateAngles), 50, 100, DefaultPixelType)] + public void Rotate_WithAngle(TestImageProvider provider, float value) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -61,22 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms image.DebugSave(provider, value); } } - - [Theory] - [WithTestPatternImages(nameof(ResamplerNames), 100, 50, DefaultPixelType)] - [WithTestPatternImages(nameof(ResamplerNames), 50, 100, DefaultPixelType)] - public void RotateWithSampler(TestImageProvider provider, string resamplerName) - where TPixel : struct, IPixel - { - IResampler resampler = GetResampler(resamplerName); - - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Rotate(50, resampler)); - image.DebugSave(provider, resamplerName); - } - } - + [Theory] [WithTestPatternImages(nameof(RotateEnumValues), 100, 50, DefaultPixelType)] [WithTestPatternImages(nameof(RotateEnumValues), 50, 100, DefaultPixelType)] @@ -89,17 +53,5 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms image.DebugSave(provider, value); } } - - private static IResampler GetResampler(string name) - { - PropertyInfo property = typeof(KnownResamplers).GetTypeInfo().GetProperty(name); - - if (property == null) - { - throw new Exception("Invalid property name!"); - } - - return (IResampler)property.GetValue(null); - } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformTests.cs index 129fe1be3..c4a9437d5 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformTests.cs @@ -1,20 +1,19 @@ using System; -using System.Collections.Generic; +using System.Numerics; +using System.Reflection; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Primitives; +using Xunit; +using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Processing.Transforms { - using System.Numerics; - using System.Reflection; - - using SixLabors.ImageSharp.PixelFormats; - using SixLabors.ImageSharp.Processing; - using SixLabors.Primitives; - - using Xunit; - - public class TransformTests : FileTestBase + public class TransformTests { + private readonly ITestOutputHelper Output; + public static readonly TheoryData TransformValues = new TheoryData { @@ -45,8 +44,37 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms nameof(KnownResamplers.Welch), }; + public TransformTests(ITestOutputHelper output) + { + this.Output = output; + } + + /// + /// The output of an "all white" image should be "all white" or transparent, regardless of the transformation and the resampler. + /// + [Theory] + [WithSolidFilledImages(5, 5, 255, 255, 255, 255, PixelTypes.Rgba32, nameof(KnownResamplers.NearestNeighbor))] + [WithSolidFilledImages(5, 5, 255, 255, 255, 255, PixelTypes.Rgba32, nameof(KnownResamplers.Triangle))] + [WithSolidFilledImages(5, 5, 255, 255, 255, 255, PixelTypes.Rgba32, nameof(KnownResamplers.Bicubic))] + [WithSolidFilledImages(5, 5, 255, 255, 255, 255, PixelTypes.Rgba32, nameof(KnownResamplers.Lanczos8))] + public void Transform_DoesNotCreateEdgeArtifacts(TestImageProvider provider, string resamplerName) + where TPixel : struct, IPixel + { + IResampler resampler = GetResampler(resamplerName); + using (Image image = provider.GetImage()) + { + // TODO: Modify this matrix if we change our origin-concept + var rotate = Matrix3x2.CreateRotation((float)Math.PI/4f); + + image.Mutate(c => c.Transform(rotate, resampler)); + image.DebugSave(provider, resamplerName); + + VerifyAllPixelsAreWhiteOrTransparent(image); + } + } + [Theory] - [WithTestPatternImages(nameof(TransformValues), 100, 50, DefaultPixelType)] + [WithTestPatternImages(nameof(TransformValues), 100, 50, PixelTypes.Rgba32)] public void Transform_RotateScaleTranslate( TestImageProvider provider, float angleDeg, @@ -57,16 +85,19 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms using (Image image = provider.GetImage()) { Matrix3x2 rotate = Matrix3x2Extensions.CreateRotationDegrees(angleDeg); - Matrix3x2 translate = Matrix3x2Extensions.CreateTranslation(new PointF(tx, ty)); - Matrix3x2 scale = Matrix3x2Extensions.CreateScale(new SizeF(sx, sy)); + var translate = Matrix3x2.CreateTranslation(tx, ty); + var scale = Matrix3x2.CreateScale(sx, sy); + Matrix3x2 m = rotate * scale * translate; + + this.Output.WriteLine(m.ToString()); - image.Mutate(i => i.Transform(rotate * scale * translate)); + image.Mutate(i => i.Transform(m)); image.DebugSave(provider, $"R({angleDeg})_S({sx},{sy})_T({tx},{ty})"); } } [Theory] - [WithTestPatternImages(nameof(ResamplerNames), 100, 200, DefaultPixelType)] + [WithTestPatternImages(nameof(ResamplerNames), 100, 200, PixelTypes.Rgba32)] public void Transform_WithSampler(TestImageProvider provider, string resamplerName) where TPixel : struct, IPixel { @@ -92,5 +123,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms return (IResampler)property.GetValue(null); } + + private static void VerifyAllPixelsAreWhiteOrTransparent(Image image) + where TPixel : struct, IPixel + { + TPixel[] data = new TPixel[image.Width * image.Height]; + image.Frames.RootFrame.SavePixelData(data); + var rgba = default(Rgba32); + var white = new Rgb24(255, 255, 255); + foreach (TPixel pixel in data) + { + pixel.ToRgba32(ref rgba); + if (rgba.A == 0) continue; + + Assert.Equal(white, rgba.Rgb); + } + } } } \ No newline at end of file