diff --git a/src/ImageSharp/Processing/AffineTransformBuilder.cs b/src/ImageSharp/Processing/AffineTransformBuilder.cs
index b2b011264..003249d6e 100644
--- a/src/ImageSharp/Processing/AffineTransformBuilder.cs
+++ b/src/ImageSharp/Processing/AffineTransformBuilder.cs
@@ -20,7 +20,13 @@ namespace SixLabors.ImageSharp.Processing
/// Initializes a new instance of the class.
///
/// The source image size.
- public AffineTransformBuilder(Size sourceSize) => this.Size = sourceSize;
+ public AffineTransformBuilder(Size sourceSize)
+ {
+ Guard.MustBeGreaterThan(sourceSize.Width, 0, nameof(sourceSize));
+ Guard.MustBeGreaterThan(sourceSize.Height, 0, nameof(sourceSize));
+
+ this.Size = sourceSize;
+ }
///
/// Initializes a new instance of the class.
@@ -41,10 +47,7 @@ namespace SixLabors.ImageSharp.Processing
/// The amount of rotation, in degrees.
/// The .
public AffineTransformBuilder PrependRotateMatrixDegrees(float degrees)
- {
- this.PrependMatrix(TransformUtils.CreateRotationMatrixDegrees(degrees, this.Size));
- return this;
- }
+ => this.PrependMatrix(TransformUtils.CreateRotationMatrixDegrees(degrees, this.Size));
///
/// Appends a centered rotation matrix using the given rotation in degrees.
@@ -52,10 +55,7 @@ namespace SixLabors.ImageSharp.Processing
/// The amount of rotation, in degrees.
/// The .
public AffineTransformBuilder AppendRotateMatrixDegrees(float degrees)
- {
- this.AppendMatrix(TransformUtils.CreateRotationMatrixDegrees(degrees, this.Size));
- return this;
- }
+ => this.AppendMatrix(TransformUtils.CreateRotationMatrixDegrees(degrees, this.Size));
///
/// Prepends a scale matrix from the given vector scale.
@@ -63,10 +63,7 @@ namespace SixLabors.ImageSharp.Processing
/// The horizontal and vertical scale.
/// The .
public AffineTransformBuilder PrependScaleMatrix(SizeF scales)
- {
- this.PrependMatrix(Matrix3x2Extensions.CreateScale(scales));
- return this;
- }
+ => this.PrependMatrix(Matrix3x2Extensions.CreateScale(scales));
///
/// Appends a scale matrix from the given vector scale.
@@ -74,10 +71,7 @@ namespace SixLabors.ImageSharp.Processing
/// The horizontal and vertical scale.
/// The .
public AffineTransformBuilder AppendScaleMatrix(SizeF scales)
- {
- this.AppendMatrix(Matrix3x2Extensions.CreateScale(scales));
- return this;
- }
+ => this.AppendMatrix(Matrix3x2Extensions.CreateScale(scales));
///
/// Prepends a centered skew matrix from the give angles in degrees.
@@ -86,10 +80,7 @@ namespace SixLabors.ImageSharp.Processing
/// The Y angle, in degrees.
/// The .
public AffineTransformBuilder PrependSkewMatrixDegrees(float degreesX, float degreesY)
- {
- this.PrependMatrix(TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, this.Size));
- return this;
- }
+ => this.PrependMatrix(TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, this.Size));
///
/// Appends a centered skew matrix from the give angles in degrees.
@@ -98,10 +89,7 @@ namespace SixLabors.ImageSharp.Processing
/// The Y angle, in degrees.
/// The .
public AffineTransformBuilder AppendSkewMatrixDegrees(float degreesX, float degreesY)
- {
- this.AppendMatrix(TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, this.Size));
- return this;
- }
+ => this.AppendMatrix(TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, this.Size));
///
/// Prepends a translation matrix from the given vector.
@@ -109,10 +97,7 @@ namespace SixLabors.ImageSharp.Processing
/// The translation position.
/// The .
public AffineTransformBuilder PrependTranslationMatrix(PointF position)
- {
- this.PrependMatrix(Matrix3x2Extensions.CreateTranslation(position));
- return this;
- }
+ => this.PrependMatrix(Matrix3x2Extensions.CreateTranslation(position));
///
/// Appends a translation matrix from the given vector.
@@ -120,10 +105,7 @@ namespace SixLabors.ImageSharp.Processing
/// The translation position.
/// The .
public AffineTransformBuilder AppendTranslationMatrix(PointF position)
- {
- this.AppendMatrix(Matrix3x2Extensions.CreateTranslation(position));
- return this;
- }
+ => this.AppendMatrix(Matrix3x2Extensions.CreateTranslation(position));
///
/// Prepends a raw matrix.
diff --git a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
index 529dd56b1..be4c67518 100644
--- a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
+++ b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
@@ -20,7 +20,13 @@ namespace SixLabors.ImageSharp.Processing
/// Initializes a new instance of the class.
///
/// The source image size.
- public ProjectiveTransformBuilder(Size sourceSize) => this.Size = sourceSize;
+ public ProjectiveTransformBuilder(Size sourceSize)
+ {
+ Guard.MustBeGreaterThan(sourceSize.Width, 0, nameof(sourceSize));
+ Guard.MustBeGreaterThan(sourceSize.Height, 0, nameof(sourceSize));
+
+ this.Size = sourceSize;
+ }
///
/// Initializes a new instance of the class.
@@ -43,10 +49,7 @@ namespace SixLabors.ImageSharp.Processing
/// The amount to taper.
/// The .
public ProjectiveTransformBuilder PrependTaperMatrix(TaperSide side, TaperCorner corner, float fraction)
- {
- this.PrependMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction));
- return this;
- }
+ => this.PrependMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction));
///
/// Appends a matrix that performs a tapering projective transform.
@@ -56,10 +59,7 @@ namespace SixLabors.ImageSharp.Processing
/// The amount to taper.
/// The .
public ProjectiveTransformBuilder AppendTaperMatrix(TaperSide side, TaperCorner corner, float fraction)
- {
- this.AppendMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction));
- return this;
- }
+ => this.AppendMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction));
///
/// Prepends a raw matrix.
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs
new file mode 100644
index 000000000..eaa51b129
--- /dev/null
+++ b/tests/ImageSharp.Tests/Processing/Transforms/AffineTransformBuilderTests.cs
@@ -0,0 +1,79 @@
+// 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 AffineTransformBuilderTests
+ {
+ [Fact]
+ public void ConstructorAssignsProperties()
+ {
+ var s = new Size(1, 1);
+ var builder = new AffineTransformBuilder(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 AffineTransformBuilder(new Rectangle(Point.Empty, s));
+ });
+
+ Assert.Throws(() =>
+ {
+ var s = new Size(1, 0);
+ var builder = new AffineTransformBuilder(new Rectangle(Point.Empty, s));
+ });
+ }
+
+ [Fact]
+ public void AppendPrependOpposite()
+ {
+ var rectangle = new Rectangle(-1, -1, 3, 3);
+ var b1 = new AffineTransformBuilder(rectangle);
+ var b2 = new AffineTransformBuilder(rectangle);
+
+ const float pi = (float)Math.PI;
+
+ // Forwards
+ b1.AppendRotateMatrixDegrees(pi)
+ .AppendSkewMatrixDegrees(pi, pi)
+ .AppendScaleMatrix(new SizeF(pi, pi))
+ .AppendTranslationMatrix(new PointF(pi, pi));
+
+ // Backwards
+ b2.PrependTranslationMatrix(new PointF(pi, pi))
+ .PrependScaleMatrix(new SizeF(pi, pi))
+ .PrependSkewMatrixDegrees(pi, pi)
+ .PrependRotateMatrixDegrees(pi);
+
+ Assert.Equal(b1.BuildMatrix(), b2.BuildMatrix());
+ }
+
+ [Fact]
+ public void BuilderCanClear()
+ {
+ var rectangle = new Rectangle(0, 0, 3, 3);
+ var builder = new AffineTransformBuilder(rectangle);
+ Matrix3x2 matrix = Matrix3x2.Identity;
+ matrix.M31 = (float)Math.PI;
+
+ Assert.Equal(Matrix3x2.Identity, builder.BuildMatrix());
+
+ builder.AppendMatrix(matrix);
+ Assert.NotEqual(Matrix3x2.Identity, builder.BuildMatrix());
+
+ builder.Clear();
+ Assert.Equal(Matrix3x2.Identity, builder.BuildMatrix());
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs
new file mode 100644
index 000000000..3dfc42d4f
--- /dev/null
+++ b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformBuilderTests.cs
@@ -0,0 +1,78 @@
+// 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
+ {
+ [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));
+ });
+ }
+
+ [Fact]
+ public void AppendPrependOpposite()
+ {
+ var rectangle = new Rectangle(-1, -1, 3, 3);
+ var b1 = new ProjectiveTransformBuilder(rectangle);
+ var b2 = new ProjectiveTransformBuilder(rectangle);
+
+ const float pi = (float)Math.PI;
+
+ Matrix4x4 m4 = Matrix4x4.Identity;
+ m4.M31 = pi;
+
+ // Forwards
+ b1.AppendMatrix(m4)
+ .AppendTaperMatrix(TaperSide.Left, TaperCorner.LeftOrTop, pi);
+
+ // Backwards
+ b2.PrependTaperMatrix(TaperSide.Left, TaperCorner.LeftOrTop, pi)
+ .PrependMatrix(m4);
+
+ Assert.Equal(b1.BuildMatrix(), b2.BuildMatrix());
+ }
+
+ [Fact]
+ public void BuilderCanClear()
+ {
+ var rectangle = new Rectangle(0, 0, 3, 3);
+ var builder = new ProjectiveTransformBuilder(rectangle);
+ Matrix4x4 matrix = Matrix4x4.Identity;
+ matrix.M31 = (float)Math.PI;
+
+ Assert.Equal(Matrix4x4.Identity, builder.BuildMatrix());
+
+ builder.AppendMatrix(matrix);
+ Assert.NotEqual(Matrix4x4.Identity, builder.BuildMatrix());
+
+ builder.Clear();
+ Assert.Equal(Matrix4x4.Identity, builder.BuildMatrix());
+ }
+ }
+}