diff --git a/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs b/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs index 0230b7a86..075ea2d52 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs @@ -8,11 +8,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public interface ISwizzler { + /// + /// Gets the size of the image after transformation. + /// + Size DestinationSize { get; } + /// /// Applies the swizzle transformation to a given point. /// /// Point to transform. - /// Transformed point. - Point Transform(Point point); + /// The transformed point. + void Transform(Point point, out Point newPoint); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs index a42a4bf77..c9b9b4570 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs @@ -1,31 +1,38 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - internal class SwizzleProcessor : ImageProcessor + internal class SwizzleProcessor : TransformProcessor where TSwizzler : struct, ISwizzler where TPixel : unmanaged, IPixel { private readonly TSwizzler swizzler; + private readonly Size destinationSize; public SwizzleProcessor(Configuration configuration, TSwizzler swizzler, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) { this.swizzler = swizzler; + this.destinationSize = swizzler.DestinationSize; } - /// - protected override void OnFrameApply(ImageFrame source) + protected override Size GetDestinationSize() + => this.destinationSize; + + protected override void OnFrameApply(ImageFrame source, ImageFrame destination) { - for (int y = 0; y < source.Height; y++) + Point p = default; + Point newPoint; + for (p.Y = 0; p.Y < source.Height; p.Y++) { - var pixelRowSpan = source.GetPixelRowSpan(y); - for (int x = 0; x < source.Width; x++) + for (p.X = 0; p.X < source.Width; p.X++) { - var newPoint = this.swizzler.Transform(new Point(x, y)); + this.swizzler.Transform(p, out newPoint); + destination[newPoint.X, newPoint.Y] = source[p.X, p.Y]; } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs index e5b95e673..d48257334 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs @@ -17,7 +17,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The swizzler operation. public SwizzleProcessor(TSwizzler swizzler) - => this.Swizzler = swizzler; + { + this.Swizzler = swizzler; + } /// /// Gets the swizzler operation. @@ -27,6 +29,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel - => new SwizzleProcessor(configuration, this, source, sourceRectangle); + => new SwizzleProcessor(configuration, this.Swizzler, source, sourceRectangle); } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs new file mode 100644 index 000000000..b951a7fb0 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs @@ -0,0 +1,35 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Extensions.Transforms; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms +{ + [GroupOutput("Transforms")] + public class SwizzleTests + { + private struct InvertXAndYSwizzler : ISwizzler + { + public Size DestinationSize => new Size(10, 10); + + public void Transform(Point point, out Point newPoint) + => newPoint = new Point(point.Y, point.X); + } + + [Theory] + [WithTestPatternImages(20, 37, PixelTypes.Rgba32)] + [WithTestPatternImages(53, 37, PixelTypes.Byte4)] + [WithTestPatternImages(17, 32, PixelTypes.Rgba32)] + public void InvertXAndYSwizzle(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + provider.RunValidatingProcessorTest( + ctx => ctx.Swizzle(default(InvertXAndYSwizzler)), + testOutputDetails: nameof(InvertXAndYSwizzler), + appendPixelTypeToFileName: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs index 2862df212..c54bfa25e 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs @@ -11,21 +11,29 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms { private struct InvertXAndYSwizzler : ISwizzler { - public Point Transform(Point point) => new Point(point.Y, point.X); + public Size DestinationSize => new Size(10, 10); + + public void Transform(Point point, out Point newPoint) + => newPoint = new Point(point.Y, point.X); } [Fact] - public void RotateDegreesFloatRotateProcessorWithAnglesSet() + public void InvertXAndYSwizzlerSetsCorrectSizes() { + int width = 5; + int height = 10; + this.operations.Swizzle(default(InvertXAndYSwizzler)); SwizzleProcessor processor = this.Verify>(); - // assert that pixels have been changed + Assert.Equal(processor.Swizzler.DestinationSize.Width, height); + Assert.Equal(processor.Swizzler.DestinationSize.Height, width); this.operations.Swizzle(default(InvertXAndYSwizzler)); - SwizzleProcessor processor2 = this.Verify>(); + SwizzleProcessor processor2 = this.Verify>(1); - // assert that pixels have been changed (i.e. back to original) + Assert.Equal(processor2.Swizzler.DestinationSize.Width, width); + Assert.Equal(processor2.Swizzler.DestinationSize.Height, height); } } }