From d992d85ef0c3c32d92b56c32a754f07f704dfa5a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 27 Nov 2018 00:46:32 +0000 Subject: [PATCH] Match APIs --- .../Processing/AffineTransformBuilder.cs | 114 +++++----- .../ProjectiveTransformProcessor.cs | 6 +- .../Processing/ProjectiveTransformBuilder.cs | 210 ++++++++---------- .../Processing/TransformExtensions.cs | 96 +++++--- .../Transforms/AffineTransformBuilderTests.cs | 15 +- .../ProjectiveTransformBuilderTests.cs | 40 +--- .../Transforms/ProjectiveTransformTests.cs | 6 +- .../Transforms/TransformBuilderTestBase.cs | 12 +- 8 files changed, 246 insertions(+), 253 deletions(-) diff --git a/src/ImageSharp/Processing/AffineTransformBuilder.cs b/src/ImageSharp/Processing/AffineTransformBuilder.cs index ed5aa987f..29c37d7bf 100644 --- a/src/ImageSharp/Processing/AffineTransformBuilder.cs +++ b/src/ImageSharp/Processing/AffineTransformBuilder.cs @@ -17,22 +17,13 @@ namespace SixLabors.ImageSharp.Processing private readonly List> matrixFactories = new List>(); /// - /// Prepends a centered rotation matrix using the given rotation in radians. - /// - /// The amount of rotation, in radians. - /// The rotation center point - /// The . - public AffineTransformBuilder PrependRotationRadians(float radians, Vector2 centerPoint) - => this.PrependMatrix(Matrix3x2.CreateRotation(radians, centerPoint)); - - /// - /// Appends a centered rotation matrix using the given rotation in radians. + /// Prepends a rotation matrix using the given rotation angle in degrees + /// and the image center point as rotation center. /// - /// The amount of rotation, in radians. - /// The rotation center point + /// The amount of rotation, in degrees. /// The . - public AffineTransformBuilder AppendRotationRadians(float radians, Vector2 centerPoint) - => this.AppendMatrix(Matrix3x2.CreateRotation(radians, centerPoint)); + public AffineTransformBuilder PrependRotationDegrees(float degrees) + => this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); /// /// Prepends a rotation matrix using the given rotation angle in radians @@ -44,31 +35,40 @@ namespace SixLabors.ImageSharp.Processing => this.Prepend(size => TransformUtils.CreateRotationMatrixRadians(radians, size)); /// - /// Appends a rotation matrix using the given rotation angle in radians - /// and the image center point as rotation center. + /// Prepends a centered rotation matrix using the given rotation in radians. /// /// The amount of rotation, in radians. + /// The rotation origin point. /// The . - public AffineTransformBuilder AppendRotationRadians(float radians) - => this.Append(size => TransformUtils.CreateRotationMatrixRadians(radians, size)); + public AffineTransformBuilder PrependRotationRadians(float radians, Vector2 origin) + => this.PrependMatrix(Matrix3x2.CreateRotation(radians, origin)); /// - /// Prepends a rotation matrix using the given rotation angle in degrees + /// Appends a rotation matrix using the given rotation angle in degrees /// and the image center point as rotation center. /// /// The amount of rotation, in degrees. /// The . - public AffineTransformBuilder PrependRotationDegrees(float degrees) - => this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); + public AffineTransformBuilder AppendRotationDegrees(float degrees) + => this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); /// - /// Appends a rotation matrix using the given rotation angle in degrees + /// Appends a rotation matrix using the given rotation angle in radians /// and the image center point as rotation center. /// - /// The amount of rotation, in degrees. + /// The amount of rotation, in radians. /// The . - public AffineTransformBuilder AppendRotationDegrees(float degrees) - => this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); + public AffineTransformBuilder AppendRotationRadians(float radians) + => this.Append(size => TransformUtils.CreateRotationMatrixRadians(radians, size)); + + /// + /// Appends a centered rotation matrix using the given rotation in radians. + /// + /// The amount of rotation, in radians. + /// The rotation origin point. + /// The . + public AffineTransformBuilder AppendRotationRadians(float radians, Vector2 origin) + => this.AppendMatrix(Matrix3x2.CreateRotation(radians, origin)); /// /// Prepends a scale matrix from the given uniform scale. @@ -79,12 +79,12 @@ namespace SixLabors.ImageSharp.Processing => this.PrependMatrix(Matrix3x2.CreateScale(scale)); /// - /// Appends a scale matrix from the given uniform scale. + /// Prepends a scale matrix from the given vector scale. /// - /// The uniform scale. + /// The horizontal and vertical scale. /// The . - public AffineTransformBuilder AppendScale(float scale) - => this.AppendMatrix(Matrix3x2.CreateScale(scale)); + public AffineTransformBuilder PrependScale(SizeF scale) + => this.PrependScale((Vector2)scale); /// /// Prepends a scale matrix from the given vector scale. @@ -95,28 +95,28 @@ namespace SixLabors.ImageSharp.Processing => this.PrependMatrix(Matrix3x2.CreateScale(scales)); /// - /// Appends a scale matrix from the given vector scale. + /// Appends a scale matrix from the given uniform scale. /// - /// The horizontal and vertical scale. + /// The uniform scale. /// The . - public AffineTransformBuilder AppendScale(Vector2 scales) - => this.AppendMatrix(Matrix3x2.CreateScale(scales)); + public AffineTransformBuilder AppendScale(float scale) + => this.AppendMatrix(Matrix3x2.CreateScale(scale)); /// - /// Prepends a scale matrix from the given vector scale. + /// Appends a scale matrix from the given vector scale. /// - /// The horizontal and vertical scale. + /// The horizontal and vertical scale. /// The . - public AffineTransformBuilder PrependScale(SizeF scale) - => this.PrependScale((Vector2)scale); + public AffineTransformBuilder AppendScale(SizeF scales) + => this.AppendScale((Vector2)scales); /// /// Appends a scale matrix from the given vector scale. /// /// The horizontal and vertical scale. /// The . - public AffineTransformBuilder AppendScale(SizeF scales) - => this.AppendScale((Vector2)scales); + public AffineTransformBuilder AppendScale(Vector2 scales) + => this.AppendMatrix(Matrix3x2.CreateScale(scales)); /// /// Prepends a centered skew matrix from the give angles in degrees. @@ -141,66 +141,58 @@ namespace SixLabors.ImageSharp.Processing /// /// The translation position. /// The . - public AffineTransformBuilder PrependTranslation(Vector2 position) - => this.PrependMatrix(Matrix3x2.CreateTranslation(position)); + public AffineTransformBuilder PrependTranslation(PointF position) + => this.PrependTranslation((Vector2)position); /// - /// Appends a translation matrix from the given vector. + /// Prepends a translation matrix from the given vector. /// /// The translation position. /// The . - public AffineTransformBuilder AppendTranslation(Vector2 position) - => this.AppendMatrix(Matrix3x2.CreateTranslation(position)); + public AffineTransformBuilder PrependTranslation(Vector2 position) + => this.PrependMatrix(Matrix3x2.CreateTranslation(position)); /// - /// Prepends a translation matrix from the given vector. + /// Appends a translation matrix from the given vector. /// /// The translation position. /// The . - public AffineTransformBuilder PrependTranslation(PointF position) - => this.PrependTranslation((Vector2)position); + public AffineTransformBuilder AppendTranslation(PointF position) + => this.AppendTranslation((Vector2)position); /// /// Appends a translation matrix from the given vector. /// /// The translation position. /// The . - public AffineTransformBuilder AppendTranslation(PointF position) - => this.AppendTranslation((Vector2)position); + public AffineTransformBuilder AppendTranslation(Vector2 position) + => this.AppendMatrix(Matrix3x2.CreateTranslation(position)); /// /// Prepends a raw matrix. /// /// The matrix to prepend. /// The . - public AffineTransformBuilder PrependMatrix(Matrix3x2 matrix) - { - this.matrixFactories.Insert(0, _ => matrix); - return this; - } + public AffineTransformBuilder PrependMatrix(Matrix3x2 matrix) => this.Prepend(_ => matrix); /// /// Appends a raw matrix. /// /// The matrix to append. /// The . - public AffineTransformBuilder AppendMatrix(Matrix3x2 matrix) - { - this.matrixFactories.Add(_ => matrix); - return this; - } + public AffineTransformBuilder AppendMatrix(Matrix3x2 matrix) => this.Append(_ => matrix); /// /// Returns the combined matrix for a given source size. /// - /// The source image size + /// The source image size. /// The . public Matrix3x2 BuildMatrix(Size sourceSize) => this.BuildMatrix(new Rectangle(Point.Empty, sourceSize)); /// /// Returns the combined matrix for a given source rectangle. /// - /// The rectangle in the source image + /// The rectangle in the source image. /// The . public Matrix3x2 BuildMatrix(Rectangle sourceRectangle) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index bfde1769c..273156e2e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -24,13 +24,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The transform matrix. /// The sampler to perform the transform operation. - /// The source image size. - public ProjectiveTransformProcessor(Matrix4x4 matrix, IResampler sampler, Size sourceSize) + /// The target dimensions. + public ProjectiveTransformProcessor(Matrix4x4 matrix, IResampler sampler, Size targetDimensions) { Guard.NotNull(sampler, nameof(sampler)); this.Sampler = sampler; this.TransformMatrix = matrix; - this.TargetDimensions = TransformUtils.GetTransformedSize(sourceSize, matrix); + this.TargetDimensions = targetDimensions; } /// diff --git a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs index 750f2f5d0..a905467bb 100644 --- a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs +++ b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Collections.Generic; using System.Numerics; using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -13,34 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// public class ProjectiveTransformBuilder { - private readonly List matrices = new List(); - private Rectangle sourceRectangle; - - /// - /// Initializes a new instance of the class. - /// - /// The source image size. - public ProjectiveTransformBuilder(Size sourceSize) - : this(new Rectangle(Point.Empty, sourceSize)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The source rectangle. - public ProjectiveTransformBuilder(Rectangle sourceRectangle) - { - Guard.MustBeGreaterThan(sourceRectangle.Width, 0, nameof(sourceRectangle)); - Guard.MustBeGreaterThan(sourceRectangle.Height, 0, nameof(sourceRectangle)); - - this.sourceRectangle = sourceRectangle; - } - - /// - /// Gets the source image size. - /// - internal Size Size => this.sourceRectangle.Size; + private readonly List> matrixFactories = new List>(); /// /// Prepends a matrix that performs a tapering projective transform. @@ -50,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount to taper. /// The . public ProjectiveTransformBuilder PrependTaper(TaperSide side, TaperCorner corner, float fraction) - => this.PrependMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction)); + => this.Prepend(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); /// /// Appends a matrix that performs a tapering projective transform. @@ -60,7 +34,15 @@ namespace SixLabors.ImageSharp.Processing /// The amount to taper. /// The . public ProjectiveTransformBuilder AppendTaper(TaperSide side, TaperCorner corner, float fraction) - => this.AppendMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction)); + => this.Append(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); + + /// + /// Prepends a centered rotation matrix using the given rotation in degrees. + /// + /// The amount of rotation, in degrees. + /// The . + public ProjectiveTransformBuilder PrependRotationDegrees(float degrees) + => this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); /// /// Prepends a centered rotation matrix using the given rotation in radians. @@ -68,33 +50,32 @@ namespace SixLabors.ImageSharp.Processing /// The amount of rotation, in radians. /// The . public ProjectiveTransformBuilder PrependRotationRadians(float radians) - { - var m = new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, this.Size)); - return this.PrependMatrix(m); - } + => this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); /// /// Appends a centered rotation matrix using the given rotation in radians. /// /// The amount of rotation, in radians. + /// The rotation center. /// The . - public ProjectiveTransformBuilder AppendRotationRadians(float radians) - { - var m = new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, this.Size)); - return this.AppendMatrix(m); - } + internal ProjectiveTransformBuilder PrependRotationRadians(float radians, Vector2 centerPoint) + => this.PrependMatrix(Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0))); + + /// + /// Appends a centered rotation matrix using the given rotation in degrees. + /// + /// The amount of rotation, in degrees. + /// The . + public ProjectiveTransformBuilder AppendRotationDegrees(float degrees) + => this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); /// /// Appends a centered rotation matrix using the given rotation in radians. /// /// The amount of rotation, in radians. - /// The rotation center. /// The . - internal ProjectiveTransformBuilder PrependRotationRadians(float radians, Vector2 centerPoint) - { - var m = Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0)); - return this.PrependMatrix(m); - } + public ProjectiveTransformBuilder AppendRotationRadians(float radians) + => this.Append(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); /// /// Appends a centered rotation matrix using the given rotation in radians. @@ -103,80 +84,69 @@ namespace SixLabors.ImageSharp.Processing /// The rotation center. /// The . internal ProjectiveTransformBuilder AppendRotationRadians(float radians, Vector2 centerPoint) - { - var m = Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0)); - return this.AppendMatrix(m); - } + => this.AppendMatrix(Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0))); /// - /// Prepends a centered rotation matrix using the given rotation in degrees. + /// Prepends a scale matrix from the given uniform scale. /// - /// The amount of rotation, in degrees. - /// The . - public ProjectiveTransformBuilder PrependCenteredRotationDegrees(float degrees) - => this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); + /// The uniform scale. + /// The . + public ProjectiveTransformBuilder PrependScale(float scale) + => this.PrependMatrix(Matrix4x4.CreateScale(scale)); /// - /// Appends a centered rotation matrix using the given rotation in degrees. + /// Prepends a scale matrix from the given vector scale. /// - /// The amount of rotation, in degrees. - /// The . - public ProjectiveTransformBuilder AppendRotationDegrees(float degrees) - => this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); + /// The horizontal and vertical scale. + /// The . + public ProjectiveTransformBuilder PrependScale(SizeF scale) + => this.PrependScale((Vector2)scale); /// - /// Prepends a scale matrix from the given uniform scale. + /// Prepends a scale matrix from the given vector scale. /// - /// The uniform scale. - /// The . - public ProjectiveTransformBuilder PrependScale(float scale) - => this.PrependMatrix(Matrix4x4.CreateScale(scale)); + /// The horizontal and vertical scale. + /// The . + public ProjectiveTransformBuilder PrependScale(Vector2 scales) + => this.PrependMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1F))); /// /// Appends a scale matrix from the given uniform scale. /// /// The uniform scale. - /// The . + /// The . public ProjectiveTransformBuilder AppendScale(float scale) => this.AppendMatrix(Matrix4x4.CreateScale(scale)); /// - /// Prepends a scale matrix from the given vector scale. + /// Appends a scale matrix from the given vector scale. /// /// The horizontal and vertical scale. - /// The . - public ProjectiveTransformBuilder PrependScale(Vector2 scales) - => this.PrependMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1f))); + /// The . + public ProjectiveTransformBuilder AppendScale(SizeF scales) + => this.AppendScale((Vector2)scales); /// /// Appends a scale matrix from the given vector scale. /// /// The horizontal and vertical scale. - /// The . + /// The . public ProjectiveTransformBuilder AppendScale(Vector2 scales) - => this.AppendMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1f))); - - /// - /// Prepends a scale matrix from the given vector scale. - /// - /// The horizontal and vertical scale. - /// The . - public ProjectiveTransformBuilder PrependScale(SizeF scale) - => this.PrependScale((Vector2)scale); + => this.AppendMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1F))); /// - /// Appends a scale matrix from the given vector scale. + /// Prepends a translation matrix from the given vector. /// - /// The horizontal and vertical scale. - /// The . - public ProjectiveTransformBuilder AppendScale(SizeF scales) - => this.AppendScale((Vector2)scales); + /// The translation position. + /// The . + public ProjectiveTransformBuilder PrependTranslation(PointF position) + => this.PrependTranslation((Vector2)position); /// /// Prepends a translation matrix from the given vector. /// /// The translation position. - /// The . + /// The . public ProjectiveTransformBuilder PrependTranslation(Vector2 position) => this.PrependMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); @@ -184,68 +154,72 @@ namespace SixLabors.ImageSharp.Processing /// Appends a translation matrix from the given vector. /// /// The translation position. - /// The . - public ProjectiveTransformBuilder AppendTranslation(Vector2 position) - => this.AppendMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); - - /// - /// Prepends a translation matrix from the given vector. - /// - /// The translation position. - /// The . - public ProjectiveTransformBuilder PrependTranslation(PointF position) - => this.PrependTranslation((Vector2)position); + /// The . + public ProjectiveTransformBuilder AppendTranslation(PointF position) + => this.AppendTranslation((Vector2)position); /// /// Appends a translation matrix from the given vector. /// /// The translation position. - /// The . - public ProjectiveTransformBuilder AppendTranslation(PointF position) - => this.AppendTranslation((Vector2)position); + /// The . + public ProjectiveTransformBuilder AppendTranslation(Vector2 position) + => this.AppendMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); /// /// Prepends a raw matrix. /// /// The matrix to prepend. /// The . - public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix) - { - this.matrices.Insert(0, matrix); - return this; - } + public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix) => this.Prepend(_ => matrix); /// /// Appends a raw matrix. /// /// The matrix to append. /// The . - public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix) - { - this.matrices.Add(matrix); - return this; - } + public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix) => this.Append(_ => matrix); + + /// + /// Returns the combined matrix for a given source size. + /// + /// The source image size. + /// The . + public Matrix4x4 BuildMatrix(Size sourceSize) => this.BuildMatrix(new Rectangle(Point.Empty, sourceSize)); /// - /// Returns the combined matrix. + /// Returns the combined matrix for a given source rectangle. /// + /// The rectangle in the source image. /// The . - public Matrix4x4 BuildMatrix() + public Matrix4x4 BuildMatrix(Rectangle sourceRectangle) { - Matrix4x4 matrix = Matrix4x4.Identity; + Guard.MustBeGreaterThan(sourceRectangle.Width, 0, nameof(sourceRectangle)); + Guard.MustBeGreaterThan(sourceRectangle.Height, 0, nameof(sourceRectangle)); // Translate the origin matrix to cater for source rectangle offsets. - if (!this.sourceRectangle.Equals(default)) - { - matrix *= Matrix4x4.CreateTranslation(new Vector3(-this.sourceRectangle.Location, 0)); - } + var matrix = Matrix4x4.CreateTranslation(new Vector3(-sourceRectangle.Location, 0)); + + Size size = sourceRectangle.Size; - foreach (Matrix4x4 m in this.matrices) + foreach (Func factory in this.matrixFactories) { - matrix *= m; + matrix *= factory(size); } return matrix; } + + private ProjectiveTransformBuilder Prepend(Func factory) + { + this.matrixFactories.Insert(0, factory); + return this; + } + + private ProjectiveTransformBuilder Append(Func factory) + { + this.matrixFactories.Add(factory); + return this; + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/TransformExtensions.cs b/src/ImageSharp/Processing/TransformExtensions.cs index de4a3e5ba..db14b6baf 100644 --- a/src/ImageSharp/Processing/TransformExtensions.cs +++ b/src/ImageSharp/Processing/TransformExtensions.cs @@ -15,40 +15,32 @@ namespace SixLabors.ImageSharp.Processing public static class TransformExtensions { /// - /// Performs an affine transform of an image using the specified sampling algorithm. + /// Performs an affine transform of an image. /// /// The pixel format. - /// The . - /// The source rectangle - /// The transformation matrix. - /// The size of the result image. - /// The to perform the resampling. + /// The image to transform. + /// The affine transform builder. /// The public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, - Rectangle sourceRectangle, - Matrix3x2 transform, - Size targetDimensions, - IResampler sampler) + this IImageProcessingContext source, + AffineTransformBuilder builder) where TPixel : struct, IPixel - { - return ctx.ApplyProcessor( - new AffineTransformProcessor(transform, sampler, targetDimensions), - sourceRectangle); - } + => Transform(source, builder, KnownResamplers.Bicubic); /// - /// Performs an affine transform of an image. + /// Performs an affine transform of an image using the specified sampling algorithm. /// /// The pixel format. - /// The image to transform. + /// The . /// The affine transform builder. + /// The to perform the resampling. /// The public static IImageProcessingContext Transform( - this IImageProcessingContext source, - AffineTransformBuilder builder) + this IImageProcessingContext ctx, + AffineTransformBuilder builder, + IResampler sampler) where TPixel : struct, IPixel - => Transform(source, builder, KnownResamplers.Bicubic); + => ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); /// /// Performs an affine transform of an image using the specified sampling algorithm. @@ -76,16 +68,22 @@ namespace SixLabors.ImageSharp.Processing /// /// The pixel format. /// The . - /// The affine transform builder. + /// The source rectangle + /// The transformation matrix. + /// The size of the result image. /// The to perform the resampling. /// The public static IImageProcessingContext Transform( this IImageProcessingContext ctx, - AffineTransformBuilder builder, + Rectangle sourceRectangle, + Matrix3x2 transform, + Size targetDimensions, IResampler sampler) where TPixel : struct, IPixel { - return ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + return ctx.ApplyProcessor( + new AffineTransformProcessor(transform, sampler, targetDimensions), + sourceRectangle); } /// @@ -105,15 +103,59 @@ namespace SixLabors.ImageSharp.Processing /// Performs a projective transform of an image using the specified sampling algorithm. /// /// The pixel format. - /// The image to transform. + /// The . /// The projective transform builder. /// The to perform the resampling. /// The public static IImageProcessingContext Transform( - this IImageProcessingContext source, + this IImageProcessingContext ctx, + ProjectiveTransformBuilder builder, + IResampler sampler) + where TPixel : struct, IPixel + => ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + + /// + /// Performs a projective transform of an image using the specified sampling algorithm. + /// + /// The pixel format. + /// The . + /// The source rectangle + /// The projective transform builder. + /// The to perform the resampling. + /// The + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, + Rectangle sourceRectangle, ProjectiveTransformBuilder builder, IResampler sampler) where TPixel : struct, IPixel - => source.ApplyProcessor(new ProjectiveTransformProcessor(builder.BuildMatrix(), sampler, builder.Size)); + { + Matrix4x4 transform = builder.BuildMatrix(sourceRectangle); + Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); + return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler); + } + + /// + /// Performs a projective transform of an image using the specified sampling algorithm. + /// + /// The pixel format. + /// The . + /// The source rectangle + /// The transformation matrix. + /// The size of the result image. + /// The to perform the resampling. + /// The + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, + Rectangle sourceRectangle, + Matrix4x4 transform, + Size targetDimensions, + IResampler sampler) + where TPixel : struct, IPixel + { + return ctx.ApplyProcessor( + new ProjectiveTransformProcessor(transform, sampler, targetDimensions), + sourceRectangle); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs index e02585168..bdc66641a 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs @@ -1,28 +1,31 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Primitives; -using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Transforms { public class AffineTransformBuilderTests : TransformBuilderTestBase { protected override void AppendTranslation(AffineTransformBuilder builder, PointF translate) => builder.AppendTranslation(translate); + protected override void AppendScale(AffineTransformBuilder builder, SizeF scale) => builder.AppendScale(scale); + protected override void AppendRotationRadians(AffineTransformBuilder builder, float radians) => builder.AppendRotationRadians(radians); + protected override void AppendRotationRadians(AffineTransformBuilder builder, float radians, Vector2 center) => builder.AppendRotationRadians(radians, center); protected override void PrependTranslation(AffineTransformBuilder builder, PointF translate) => builder.PrependTranslation(translate); + protected override void PrependScale(AffineTransformBuilder builder, SizeF scale) => builder.PrependScale(scale); + protected override void PrependRotationRadians(AffineTransformBuilder builder, float radians) => builder.PrependRotationRadians(radians); - protected override void PrependRotationRadians(AffineTransformBuilder builder, float radians, Vector2 center) => - builder.PrependRotationRadians(radians, center); + + protected override void PrependRotationRadians(AffineTransformBuilder builder, float radians, Vector2 origin) => + builder.PrependRotationRadians(radians, origin); protected override AffineTransformBuilder CreateBuilder(Rectangle rectangle) => new AffineTransformBuilder(); @@ -35,4 +38,4 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms return Vector2.Transform(sourcePoint, matrix); } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs index 01448ac59..287d7be49 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs @@ -1,60 +1,40 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; -using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Transforms { public class ProjectiveTransformBuilderTests : TransformBuilderTestBase { - [Fact] - public void ConstructorAssignsProperties() - { - var s = new Size(1, 1); - var builder = new ProjectiveTransformBuilder(new Rectangle(Point.Empty, s)); - Assert.Equal(s, builder.Size); - } - - [Fact] - public void ConstructorThrowsInvalid() - { - Assert.Throws(() => - { - var s = new Size(0, 1); - var builder = new ProjectiveTransformBuilder(new Rectangle(Point.Empty, s)); - }); - - Assert.Throws(() => - { - var s = new Size(1, 0); - var builder = new ProjectiveTransformBuilder(new Rectangle(Point.Empty, s)); - }); - } - - protected override ProjectiveTransformBuilder CreateBuilder(Rectangle rectangle) => new ProjectiveTransformBuilder(rectangle); + protected override ProjectiveTransformBuilder CreateBuilder(Rectangle rectangle) => new ProjectiveTransformBuilder(); protected override void AppendTranslation(ProjectiveTransformBuilder builder, PointF translate) => builder.AppendTranslation(translate); + protected override void AppendScale(ProjectiveTransformBuilder builder, SizeF scale) => builder.AppendScale(scale); + protected override void AppendRotationRadians(ProjectiveTransformBuilder builder, float radians) => builder.AppendRotationRadians(radians); + protected override void AppendRotationRadians(ProjectiveTransformBuilder builder, float radians, Vector2 center) => builder.AppendRotationRadians(radians, center); protected override void PrependTranslation(ProjectiveTransformBuilder builder, PointF translate) => builder.PrependTranslation(translate); + protected override void PrependScale(ProjectiveTransformBuilder builder, SizeF scale) => builder.PrependScale(scale); + protected override void PrependRotationRadians(ProjectiveTransformBuilder builder, float radians) => builder.PrependRotationRadians(radians); - protected override void PrependRotationRadians(ProjectiveTransformBuilder builder, float radians, Vector2 center) => - builder.PrependRotationRadians(radians, center); + + protected override void PrependRotationRadians(ProjectiveTransformBuilder builder, float radians, Vector2 origin) => + builder.PrependRotationRadians(radians, origin); protected override Vector2 Execute( ProjectiveTransformBuilder builder, Rectangle rectangle, Vector2 sourcePoint) { - Matrix4x4 matrix = builder.BuildMatrix(); + Matrix4x4 matrix = builder.BuildMatrix(rectangle); return Vector2.Transform(sourcePoint, matrix); } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs index 9436b7828..1da660d22 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms IResampler sampler = GetResampler(resamplerName); using (Image image = provider.GetImage()) { - ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder(image.Size()) + ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder() .AppendTaper(TaperSide.Right, TaperCorner.Both, .5F); image.Mutate(i => i.Transform(builder, sampler)); @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms { using (Image image = provider.GetImage()) { - ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder(image.Size()) + ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder() .AppendTaper(taperSide, taperCorner, .5F); image.Mutate(i => i.Transform(builder)); @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms Matrix4x4 matrix = Matrix4x4.Identity; matrix.M13 = 0.01F; - ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder(image.Size()) + ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder() .AppendMatrix(matrix); image.Mutate(i => i.Transform(builder)); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs index dffa3c7ac..720c87ced 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs @@ -18,7 +18,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms new TheoryData { // scale, translate, source, expectedDest - { Vector2.One, Vector2.Zero, Vector2.Zero, Vector2.Zero }, { Vector2.One, Vector2.Zero, new Vector2(10, 20), new Vector2(10, 20) }, { Vector2.One, new Vector2(3, 1), new Vector2(10, 20), new Vector2(13, 21) }, @@ -44,7 +43,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms new TheoryData { // translate, scale, source, expectedDest - { Vector2.Zero, Vector2.One, Vector2.Zero, Vector2.Zero }, { Vector2.Zero, Vector2.One, new Vector2(10, 20), new Vector2(10, 20) }, { new Vector2(3, 1), new Vector2(2, 0.5f), new Vector2(10, 20), new Vector2(26, 10.5f) }, @@ -183,14 +181,20 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms protected abstract TBuilder CreateBuilder(Rectangle rectangle); protected abstract void AppendTranslation(TBuilder builder, PointF translate); + protected abstract void AppendScale(TBuilder builder, SizeF scale); + protected abstract void AppendRotationRadians(TBuilder builder, float radians); + protected abstract void AppendRotationRadians(TBuilder builder, float radians, Vector2 center); protected abstract void PrependTranslation(TBuilder builder, PointF translate); + protected abstract void PrependScale(TBuilder builder, SizeF scale); + protected abstract void PrependRotationRadians(TBuilder builder, float radians); - protected abstract void PrependRotationRadians(TBuilder b1, float v, Vector2 vector2); + + protected abstract void PrependRotationRadians(TBuilder builder, float radians, Vector2 origin); protected virtual void AppendRotationDegrees(TBuilder builder, float degrees) => this.AppendRotationRadians(builder, GeometryUtilities.DegreeToRadian(degrees)); @@ -199,7 +203,5 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms this.AppendRotationRadians(builder, GeometryUtilities.DegreeToRadian(degrees), center); protected abstract Vector2 Execute(TBuilder builder, Rectangle rectangle, Vector2 sourcePoint); - - private static float Sqrt(float a) => (float)Math.Sqrt(a); } } \ No newline at end of file