diff --git a/src/ImageSharp/Processing/AffineTransformBuilder.cs b/src/ImageSharp/Processing/AffineTransformBuilder.cs
index d793c67a2..1478d2951 100644
--- a/src/ImageSharp/Processing/AffineTransformBuilder.cs
+++ b/src/ImageSharp/Processing/AffineTransformBuilder.cs
@@ -247,15 +247,33 @@ namespace SixLabors.ImageSharp.Processing
/// Prepends a raw matrix.
///
/// The matrix to prepend.
+ ///
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
+ ///
/// The .
- public AffineTransformBuilder PrependMatrix(Matrix3x2 matrix) => this.Prepend(_ => matrix);
+ public AffineTransformBuilder PrependMatrix(Matrix3x2 matrix)
+ {
+ CheckDegenerate(matrix);
+ return this.Prepend(_ => matrix);
+ }
///
/// Appends a raw matrix.
///
/// The matrix to append.
+ ///
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
+ ///
/// The .
- public AffineTransformBuilder AppendMatrix(Matrix3x2 matrix) => this.Append(_ => matrix);
+ public AffineTransformBuilder AppendMatrix(Matrix3x2 matrix)
+ {
+ CheckDegenerate(matrix);
+ return this.Append(_ => matrix);
+ }
///
/// Returns the combined matrix for a given source size.
@@ -269,7 +287,9 @@ namespace SixLabors.ImageSharp.Processing
///
/// The rectangle in the source image.
///
- /// The resultant matrix contains one or more values equivalent to .
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
///
/// The .
public Matrix3x2 BuildMatrix(Rectangle sourceRectangle)
@@ -287,12 +307,17 @@ namespace SixLabors.ImageSharp.Processing
matrix *= factory(size);
}
- if (TransformUtilities.IsNaN(matrix) || matrix.GetDeterminant() == 0)
+ CheckDegenerate(matrix);
+
+ return matrix;
+ }
+
+ private static void CheckDegenerate(Matrix3x2 matrix)
+ {
+ if (TransformUtilities.IsDegenerate(matrix))
{
throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
}
-
- return matrix;
}
private AffineTransformBuilder Prepend(Func factory)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs
index 329d57f3d..b474b4371 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs
@@ -12,6 +12,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
internal static class TransformUtilities
{
+ ///
+ /// Returns a value that indicates whether the specified matrix is degenerate
+ /// containing one or more values equivalent to or a
+ /// zero determinant and therefore cannot be used for linear transforms.
+ ///
+ /// The transform matrix.
+ public static bool IsDegenerate(Matrix3x2 matrix)
+ => IsNaN(matrix) || IsZero(matrix.GetDeterminant());
+
+ ///
+ /// Returns a value that indicates whether the specified matrix is degenerate
+ /// containing one or more values equivalent to or a
+ /// zero determinant and therefore cannot be used for linear transforms.
+ ///
+ /// The transform matrix.
+ public static bool IsDegenerate(Matrix4x4 matrix)
+ => IsNaN(matrix) || IsZero(matrix.GetDeterminant());
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static bool IsZero(float a)
+ => a > -Constants.EpsilonSquared && a < Constants.EpsilonSquared;
+
///
/// Returns a value that indicates whether the specified matrix contains any values
/// that are not a number .
diff --git a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
index 0535eaeb1..b7e65b4cc 100644
--- a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
+++ b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Numerics;
+using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
namespace SixLabors.ImageSharp.Processing
@@ -263,29 +264,50 @@ namespace SixLabors.ImageSharp.Processing
/// Prepends a raw matrix.
///
/// The matrix to prepend.
+ ///
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
+ ///
/// The .
- public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix) => this.Prepend(_ => matrix);
+ public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix)
+ {
+ CheckDegenerate(matrix);
+ return this.Prepend(_ => matrix);
+ }
///
/// Appends a raw matrix.
///
/// The matrix to append.
+ ///
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
+ ///
/// The .
- public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix) => this.Append(_ => matrix);
+ public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix)
+ {
+ CheckDegenerate(matrix);
+ return 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));
+ public Matrix4x4 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 resultant matrix contains one or more values equivalent to .
+ /// The resultant matrix is degenerate containing one or more values equivalent
+ /// to or a zero determinant and therefore cannot be used
+ /// for linear transforms.
///
/// The .
public Matrix4x4 BuildMatrix(Rectangle sourceRectangle)
@@ -303,12 +325,17 @@ namespace SixLabors.ImageSharp.Processing
matrix *= factory(size);
}
- if (TransformUtilities.IsNaN(matrix) || matrix.GetDeterminant() == 0)
+ CheckDegenerate(matrix);
+
+ return matrix;
+ }
+
+ private static void CheckDegenerate(Matrix4x4 matrix)
+ {
+ if (TransformUtilities.IsDegenerate(matrix))
{
throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
}
-
- return matrix;
}
private ProjectiveTransformBuilder Prepend(Func factory)