diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs
index d7932f90b6..de4a898132 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs
@@ -340,18 +340,18 @@ internal void SyncSubject(int width, int height, Matrix4x4 matrix)
if (area.Value?.Length == 4)
{
RectangleF rectangle = new(area.Value[0], area.Value[1], area.Value[2], area.Value[3]);
- if (!TransformUtils.TryGetTransformedRectangle(rectangle, matrix, out Rectangle bounds))
+ if (!TransformUtils.TryGetTransformedRectangle(rectangle, matrix, out RectangleF bounds))
{
return;
}
// Ensure the bounds are within the image dimensions.
- bounds = Rectangle.Intersect(bounds, new Rectangle(0, 0, width, height));
+ bounds = RectangleF.Intersect(bounds, new Rectangle(0, 0, width, height));
- area.Value[0] = (ushort)bounds.X;
- area.Value[1] = (ushort)bounds.Y;
- area.Value[2] = (ushort)bounds.Width;
- area.Value[3] = (ushort)bounds.Height;
+ area.Value[0] = (ushort)MathF.Floor(bounds.X);
+ area.Value[1] = (ushort)MathF.Floor(bounds.Y);
+ area.Value[2] = (ushort)MathF.Ceiling(bounds.Width);
+ area.Value[3] = (ushort)MathF.Ceiling(bounds.Height);
this.SetValue(ExifTag.SubjectArea, area.Value);
}
else
diff --git a/src/ImageSharp/Primitives/Point.cs b/src/ImageSharp/Primitives/Point.cs
index 8ace7ffacf..8627fe980a 100644
--- a/src/ImageSharp/Primitives/Point.cs
+++ b/src/ImageSharp/Primitives/Point.cs
@@ -69,7 +69,7 @@ public Point(Size size)
/// Gets a value indicating whether this is empty.
///
[EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
+ public readonly bool IsEmpty => this.Equals(Empty);
///
/// Creates a with the coordinates of the specified .
@@ -239,7 +239,7 @@ public Point(Size size)
///
/// The out value for X.
/// The out value for Y.
- public void Deconstruct(out int x, out int y)
+ public readonly void Deconstruct(out int x, out int y)
{
x = this.X;
y = this.Y;
@@ -268,17 +268,17 @@ public void Offset(int dx, int dy)
public void Offset(Point point) => this.Offset(point.X, point.Y);
///
- public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
+ public override readonly int GetHashCode() => HashCode.Combine(this.X, this.Y);
///
- public override string ToString() => $"Point [ X={this.X}, Y={this.Y} ]";
+ public override readonly string ToString() => $"Point [ X={this.X}, Y={this.Y} ]";
///
- public override bool Equals(object? obj) => obj is Point other && this.Equals(other);
+ public override readonly bool Equals(object? obj) => obj is Point other && this.Equals(other);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Point other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
+ public readonly bool Equals(Point other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
private static short HighInt16(int n) => unchecked((short)((n >> 16) & 0xffff));
diff --git a/src/ImageSharp/Primitives/PointF.cs b/src/ImageSharp/Primitives/PointF.cs
index de363e2bd3..35a506bb41 100644
--- a/src/ImageSharp/Primitives/PointF.cs
+++ b/src/ImageSharp/Primitives/PointF.cs
@@ -58,7 +58,7 @@ public PointF(SizeF size)
/// Gets a value indicating whether this is empty.
///
[EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
+ public readonly bool IsEmpty => this.Equals(Empty);
///
/// Creates a with the coordinates of the specified .
@@ -251,7 +251,7 @@ public PointF(SizeF size)
///
/// The out value for X.
/// The out value for Y.
- public void Deconstruct(out float x, out float y)
+ public readonly void Deconstruct(out float x, out float y)
{
x = this.X;
y = this.Y;
@@ -277,15 +277,15 @@ public void Offset(float dx, float dy)
public void Offset(PointF point) => this.Offset(point.X, point.Y);
///
- public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
+ public override readonly int GetHashCode() => HashCode.Combine(this.X, this.Y);
///
- public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]";
+ public override readonly string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]";
///
- public override bool Equals(object? obj) => obj is PointF pointF && this.Equals(pointF);
+ public override readonly bool Equals(object? obj) => obj is PointF pointF && this.Equals(pointF);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
+ public readonly bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
}
diff --git a/src/ImageSharp/Primitives/SizeF.cs b/src/ImageSharp/Primitives/SizeF.cs
index 81c749875f..108ea1eed0 100644
--- a/src/ImageSharp/Primitives/SizeF.cs
+++ b/src/ImageSharp/Primitives/SizeF.cs
@@ -67,7 +67,7 @@ public SizeF(PointF point)
/// Gets a value indicating whether this is empty.
///
[EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
+ public readonly bool IsEmpty => this.Equals(Empty);
///
/// Creates a with the coordinates of the specified .
@@ -201,24 +201,24 @@ public static SizeF Transform(SizeF size, Matrix3x2 matrix)
///
/// The out value for the width.
/// The out value for the height.
- public void Deconstruct(out float width, out float height)
+ public readonly void Deconstruct(out float width, out float height)
{
width = this.Width;
height = this.Height;
}
///
- public override int GetHashCode() => HashCode.Combine(this.Width, this.Height);
+ public override readonly int GetHashCode() => HashCode.Combine(this.Width, this.Height);
///
- public override string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]";
+ public override readonly string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]";
///
- public override bool Equals(object? obj) => obj is SizeF && this.Equals((SizeF)obj);
+ public override readonly bool Equals(object? obj) => obj is SizeF sizeF && this.Equals(sizeF);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height);
+ public readonly bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height);
///
/// Multiplies by a producing .
diff --git a/src/ImageSharp/Processing/AffineTransformBuilder.cs b/src/ImageSharp/Processing/AffineTransformBuilder.cs
index 6d1e8aaa55..e330c6c263 100644
--- a/src/ImageSharp/Processing/AffineTransformBuilder.cs
+++ b/src/ImageSharp/Processing/AffineTransformBuilder.cs
@@ -17,24 +17,9 @@ public class AffineTransformBuilder
/// Initializes a new instance of the class.
///
public AffineTransformBuilder()
- : this(TransformSpace.Pixel)
{
}
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The to use when applying the affine transform.
- ///
- public AffineTransformBuilder(TransformSpace transformSpace)
- => this.TransformSpace = transformSpace;
-
- ///
- /// Gets the to use when applying the affine transform.
- ///
- public TransformSpace TransformSpace { get; }
-
///
/// Prepends a rotation matrix using the given rotation angle in degrees
/// and the image center point as rotation center.
@@ -52,7 +37,7 @@ public AffineTransformBuilder PrependRotationDegrees(float degrees)
/// The .
public AffineTransformBuilder PrependRotationRadians(float radians)
=> this.Prepend(
- size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace));
+ size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size));
///
/// Prepends a rotation matrix using the given rotation in degrees at the given origin.
@@ -88,7 +73,7 @@ public AffineTransformBuilder AppendRotationDegrees(float degrees)
/// The amount of rotation, in radians.
/// The .
public AffineTransformBuilder AppendRotationRadians(float radians)
- => this.Append(size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace));
+ => this.Append(size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size));
///
/// Appends a rotation matrix using the given rotation in degrees at the given origin.
@@ -172,7 +157,7 @@ public AffineTransformBuilder PrependSkewDegrees(float degreesX, float degreesY)
/// The Y angle, in radians.
/// The .
public AffineTransformBuilder PrependSkewRadians(float radiansX, float radiansY)
- => this.Prepend(size => TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size, this.TransformSpace));
+ => this.Prepend(size => TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size));
///
/// Prepends a skew matrix using the given angles in degrees at the given origin.
@@ -210,7 +195,7 @@ public AffineTransformBuilder AppendSkewDegrees(float degreesX, float degreesY)
/// The Y angle, in radians.
/// The .
public AffineTransformBuilder AppendSkewRadians(float radiansX, float radiansY)
- => this.Append(size => TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size, this.TransformSpace));
+ => this.Append(size => TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size));
///
/// Appends a skew matrix using the given angles in degrees at the given origin.
@@ -344,12 +329,26 @@ public Matrix3x2 BuildMatrix(Rectangle sourceRectangle)
/// for linear transforms.
///
/// The .
- public Size GetTransformedSize(Rectangle sourceRectangle)
+ public SizeF GetTransformedSize(Rectangle sourceRectangle)
{
Matrix3x2 matrix = this.BuildMatrix(sourceRectangle);
- return TransformUtils.GetTransformedSize(matrix, sourceRectangle.Size, this.TransformSpace);
+ return GetTransformedSize(sourceRectangle, matrix);
}
+ ///
+ /// Returns the size of a rectangle large enough to contain the transformed source rectangle.
+ ///
+ /// The rectangle in the source image.
+ /// The transformation matrix.
+ ///
+ /// 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 .
+ internal static SizeF GetTransformedSize(Rectangle sourceRectangle, Matrix3x2 matrix)
+ => TransformUtils.GetRawTransformedSize(matrix, sourceRectangle.Size);
+
private static void CheckDegenerate(Matrix3x2 matrix)
{
if (TransformUtils.IsDegenerate(matrix))
diff --git a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs
index 60f90b10f2..5857cb4350 100644
--- a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs
@@ -7,8 +7,8 @@
namespace SixLabors.ImageSharp.Processing;
///
-/// Defines extensions that allow the application of composable transform operations on an
-/// using Mutate/Clone.
+/// Defines extensions that allow the application of composable transform operations
+/// on an using Mutate/Clone.
///
public static class TransformExtensions
{
@@ -51,7 +51,7 @@ public static IImageProcessingContext Transform(
IResampler sampler)
{
Matrix3x2 transform = builder.BuildMatrix(sourceRectangle);
- Size targetDimensions = builder.GetTransformedSize(sourceRectangle);
+ Size targetDimensions = TransformUtils.GetTransformedCanvasSize(transform, sourceRectangle.Size);
return source.Transform(sourceRectangle, transform, targetDimensions, sampler);
}
@@ -113,7 +113,7 @@ public static IImageProcessingContext Transform(
IResampler sampler)
{
Matrix4x4 transform = builder.BuildMatrix(sourceRectangle);
- Size targetDimensions = builder.GetTransformedSize(sourceRectangle);
+ Size targetDimensions = TransformUtils.GetTransformedCanvasSize(transform, sourceRectangle.Size);
return source.Transform(sourceRectangle, transform, targetDimensions, sampler);
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
index 59f5773cf1..de9daa2fc6 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
@@ -77,7 +77,9 @@ public void ApplyTransform(in TResampler sampler)
return;
}
- // Convert from screen to world space.
+ // All matrices are defined in normalized coordinate space so we need to convert to pixel space.
+ // After normalization we need to invert the matrix for correct sampling.
+ matrix = TransformUtils.NormalizeToPixel(matrix);
Matrix3x2.Invert(matrix, out matrix);
if (sampler is NearestNeighborResampler)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
index 1c30fd1145..7af627a26c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
@@ -75,7 +75,9 @@ public void ApplyTransform(in TResampler sampler)
return;
}
- // Convert from screen to world space.
+ // All matrices are defined in normalized coordinate space so we need to convert to pixel space.
+ // After normalization we need to invert the matrix for correct sampling.
+ matrix = TransformUtils.NormalizeToPixel(matrix);
Matrix4x4.Invert(matrix, out matrix);
if (sampler is NearestNeighborResampler)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs
index 0af2b268a1..c745c480d6 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs
@@ -28,14 +28,14 @@ public RotateProcessor(float degrees, Size sourceSize)
/// The source image size
public RotateProcessor(float degrees, IResampler sampler, Size sourceSize)
: this(
- TransformUtils.CreateRotationTransformMatrixDegrees(degrees, sourceSize, TransformSpace.Pixel),
+ TransformUtils.CreateRotationTransformMatrixDegrees(degrees, sourceSize),
sampler,
sourceSize)
=> this.Degrees = degrees;
// Helper constructor
private RotateProcessor(Matrix3x2 rotationMatrix, IResampler sampler, Size sourceSize)
- : base(rotationMatrix, sampler, TransformUtils.GetTransformedSize(rotationMatrix, sourceSize, TransformSpace.Pixel))
+ : base(rotationMatrix, sampler, TransformUtils.GetTransformedCanvasSize(rotationMatrix, sourceSize))
{
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs
index 0bbc8e0f60..a5621bc4cf 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs
@@ -30,7 +30,7 @@ public SkewProcessor(float degreesX, float degreesY, Size sourceSize)
/// The source image size
public SkewProcessor(float degreesX, float degreesY, IResampler sampler, Size sourceSize)
: this(
- TransformUtils.CreateSkewTransformMatrixDegrees(degreesX, degreesY, sourceSize, TransformSpace.Pixel),
+ TransformUtils.CreateSkewTransformMatrixDegrees(degreesX, degreesY, sourceSize),
sampler,
sourceSize)
{
@@ -40,7 +40,7 @@ public SkewProcessor(float degreesX, float degreesY, IResampler sampler, Size so
// Helper constructor:
private SkewProcessor(Matrix3x2 skewMatrix, IResampler sampler, Size sourceSize)
- : base(skewMatrix, sampler, TransformUtils.GetTransformedSize(skewMatrix, sourceSize, TransformSpace.Pixel))
+ : base(skewMatrix, sampler, TransformUtils.GetTransformedCanvasSize(skewMatrix, sourceSize))
{
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs
index d25d4f4749..6badd949a7 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs
@@ -80,79 +80,69 @@ public static Vector2 ProjectiveTransform2D(float x, float y, Matrix4x4 matrix)
}
///
- /// Creates a centered rotation transform matrix using the given rotation in degrees and the source size.
+ /// Creates a centered rotation transform matrix using the given rotation in degrees and The original source size.
///
/// The amount of rotation, in degrees.
/// The source image size.
- /// The to use when creating the centered matrix.
/// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Matrix3x2 CreateRotationTransformMatrixDegrees(float degrees, Size size, TransformSpace transformSpace)
- => CreateRotationTransformMatrixRadians(GeometryUtilities.DegreeToRadian(degrees), size, transformSpace);
+ public static Matrix3x2 CreateRotationTransformMatrixDegrees(float degrees, Size size)
+ => CreateRotationTransformMatrixRadians(GeometryUtilities.DegreeToRadian(degrees), size);
///
- /// Creates a centered rotation transform matrix using the given rotation in radians and the source size.
+ /// Creates a centered rotation transform matrix using the given rotation in radians and The original source size.
///
/// The amount of rotation, in radians.
/// The source image size.
- /// The to use when creating the centered matrix.
/// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Matrix3x2 CreateRotationTransformMatrixRadians(float radians, Size size, TransformSpace transformSpace)
- => CreateCenteredTransformMatrix(Matrix3x2Extensions.CreateRotation(radians, PointF.Empty), size, transformSpace);
+ public static Matrix3x2 CreateRotationTransformMatrixRadians(float radians, Size size)
+ => CreateCenteredTransformMatrix(Matrix3x2Extensions.CreateRotation(radians, PointF.Empty), size);
///
- /// Creates a centered skew transform matrix from the give angles in degrees and the source size.
+ /// Creates a centered skew transform matrix from the give angles in degrees and The original source size.
///
/// The X angle, in degrees.
/// The Y angle, in degrees.
/// The source image size.
- /// The to use when creating the centered matrix.
/// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Matrix3x2 CreateSkewTransformMatrixDegrees(float degreesX, float degreesY, Size size, TransformSpace transformSpace)
- => CreateSkewTransformMatrixRadians(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY), size, transformSpace);
+ public static Matrix3x2 CreateSkewTransformMatrixDegrees(float degreesX, float degreesY, Size size)
+ => CreateSkewTransformMatrixRadians(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY), size);
///
- /// Creates a centered skew transform matrix from the give angles in radians and the source size.
+ /// Creates a centered skew transform matrix from the give angles in radians and The original source size.
///
/// The X angle, in radians.
/// The Y angle, in radians.
/// The source image size.
- /// The to use when creating the centered matrix.
/// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Matrix3x2 CreateSkewTransformMatrixRadians(float radiansX, float radiansY, Size size, TransformSpace transformSpace)
- => CreateCenteredTransformMatrix(Matrix3x2Extensions.CreateSkew(radiansX, radiansY, PointF.Empty), size, transformSpace);
+ public static Matrix3x2 CreateSkewTransformMatrixRadians(float radiansX, float radiansY, Size size)
+ => CreateCenteredTransformMatrix(Matrix3x2Extensions.CreateSkew(radiansX, radiansY, PointF.Empty), size);
///
/// Gets the centered transform matrix based upon the source rectangle.
///
/// The transformation matrix.
/// The source image size.
- ///
- /// The to use when creating the centered matrix.
- ///
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Matrix3x2 CreateCenteredTransformMatrix(Matrix3x2 matrix, Size size, TransformSpace transformSpace)
+ public static Matrix3x2 CreateCenteredTransformMatrix(Matrix3x2 matrix, Size size)
{
- Size transformSize = GetUnboundedTransformedSize(matrix, size, transformSpace);
-
- // We invert the matrix to handle the transformation from screen to world space.
- // This ensures scaling matrices are correct.
- Matrix3x2.Invert(matrix, out Matrix3x2 inverted);
+ // 1) Unbounded size.
+ SizeF ts = GetRawTransformedSize(matrix, size);
- // The source size is provided using the coordinate space of the source image.
- // however the transform should always be applied in the pixel space.
- // To account for this we offset by the size - 1 to translate to the pixel space.
- float offset = transformSpace == TransformSpace.Pixel ? 1F : 0F;
+ // 2) Invert the content transform for screen->world.
+ Matrix3x2.Invert(matrix, out Matrix3x2 inv);
- Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(new Vector2(-(transformSize.Width - offset), -(transformSize.Height - offset)) * .5F);
- Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(new Vector2(size.Width - offset, size.Height - offset) * .5F);
+ // 3) Translate target (canvas) so its center is at the origin,
+ // translate source so its center is at the origin, then undo the content transform.
+ Matrix3x2 toTarget = Matrix3x2.CreateTranslation(new Vector2(-ts.Width, -ts.Height) * 0.5f);
+ Matrix3x2 toSource = Matrix3x2.CreateTranslation(new Vector2(size.Width, size.Height) * 0.5f);
- // Translate back to world space.
- Matrix3x2.Invert(translationToTargetCenter * inverted * translateToSourceCenter, out Matrix3x2 centered);
+ // 4) World->screen.
+ Matrix3x2.Invert(toTarget * inv * toSource, out Matrix3x2 centered);
return centered;
}
@@ -287,7 +277,6 @@ public static Matrix4x4 CreateTaperMatrix(Size size, TaperSide side, TaperCorner
/// The top-right point of the distorted quad.
/// The bottom-right point of the distorted quad.
/// The bottom-left point of the distorted quad.
- /// The to use when creating the matrix.
/// The computed projection matrix for the quad distortion.
///
/// This method is based on the algorithm described in the following article:
@@ -298,8 +287,7 @@ public static Matrix4x4 CreateQuadDistortionMatrix(
PointF topLeft,
PointF topRight,
PointF bottomRight,
- PointF bottomLeft,
- TransformSpace transformSpace)
+ PointF bottomLeft)
{
PointF p1 = new(rectangle.X, rectangle.Y);
PointF p2 = new(rectangle.X + rectangle.Width, rectangle.Y);
@@ -345,46 +333,94 @@ public static Matrix4x4 CreateQuadDistortionMatrix(
(float)b[2], (float)b[5], 0, 1);
#pragma warning restore SA1117
- // Check if the matrix involves only affine transformations by inspecting the relevant components.
- // We want to use pixel space for calculations only if the transformation is purely 2D and does not include
- // any perspective effects, non-standard scaling, or unusual translations that could distort the image.
- if (transformSpace == TransformSpace.Pixel && IsAffineRotationOrSkew(projectionMatrix))
- {
- if (projectionMatrix.M41 != 0)
- {
- projectionMatrix.M41--;
- }
-
- if (projectionMatrix.M42 != 0)
- {
- projectionMatrix.M42--;
- }
- }
-
return projectionMatrix;
}
///
- /// Returns the size relative to the source for the given transformation matrix.
+ /// Calculates the size of a destination canvas large enough to contain
+ /// the fully transformed source content, including any translation offsets.
///
/// The transformation matrix.
- /// The source size.
- /// The to use when calculating the size.
- /// The .
- public static Size GetTransformedSize(Matrix3x2 matrix, Size size, TransformSpace transformSpace)
- => GetTransformedSize(matrix, size, transformSpace, true);
+ /// The original source size.
+ ///
+ /// A representing the dimensions of the destination
+ /// canvas required to fully contain the transformed source, including
+ /// any positive or negative translation offsets.
+ ///
+ ///
+ ///
+ /// This method ensures that the transformed content remains fully visible
+ /// on the destination canvas by expanding its size to include translations
+ /// in all directions.
+ ///
+ ///
+ /// It behaves identically to calling
+ /// with
+ /// preserveCanvas set to .
+ ///
+ ///
+ /// The resulting canvas size represents the total area required to display
+ /// the transformed image without clipping, not merely the geometric bounds
+ /// of the transformed source.
+ ///
+ ///
+ public static Size GetTransformedCanvasSize(Matrix3x2 matrix, Size size)
+ => Size.Ceiling(GetTransformedSize(matrix, size, true));
///
- /// Returns the size relative to the source for the given transformation matrix.
+ /// Calculates the size of a destination canvas large enough to contain
+ /// the fully transformed source content, including any translation offsets.
///
/// The transformation matrix.
- /// The source size.
- /// The used when generating the matrix.
+ /// The original source size.
///
- /// The .
+ /// A representing the dimensions of the destination
+ /// canvas required to fully contain the transformed source, including
+ /// any positive or negative translation offsets.
///
+ ///
+ ///
+ /// This method ensures that the transformed content remains fully visible
+ /// on the destination canvas by expanding its size to include translations
+ /// in all directions.
+ ///
+ ///
+ /// It behaves identically to calling
+ /// with
+ /// preserveCanvas set to .
+ ///
+ ///
+ /// The resulting canvas size represents the total area required to display
+ /// the transformed image without clipping, not merely the geometric bounds
+ /// of the transformed source.
+ ///
+ ///
+ public static Size GetTransformedCanvasSize(Matrix4x4 matrix, Size size)
+ => Size.Ceiling(GetTransformedSize(matrix, size, true));
+
+ ///
+ /// Returns the size relative to the source for the given transformation matrix.
+ ///
+ /// The transformation matrix.
+ /// The original source size.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static SizeF GetRawTransformedSize(Matrix4x4 matrix, Size size)
+ => GetTransformedSize(matrix, size, false);
+
+ ///
+ /// Returns the size of the transformed source. When is true,
+ /// the size is expanded to include translation so the full moved content remains visible.
+ ///
+ /// The transformation matrix.
+ /// The original source size.
+ ///
+ /// If , expand the size to account for translation (left/up as well as right/down).
+ /// If , return only the transformed span without translation expansion.
+ ///
+ /// The .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Size GetTransformedSize(Matrix4x4 matrix, Size size, TransformSpace transformSpace)
+ private static SizeF GetTransformedSize(Matrix4x4 matrix, Size size, bool preserveCanvas)
{
Guard.IsTrue(size.Width > 0 && size.Height > 0, nameof(size), "Source size dimensions cannot be 0!");
@@ -393,27 +429,9 @@ public static Size GetTransformedSize(Matrix4x4 matrix, Size size, TransformSpac
return size;
}
- // Check if the matrix involves only affine transformations by inspecting the relevant components.
- // We want to use pixel space for calculations only if the transformation is purely 2D and does not include
- // any perspective effects, non-standard scaling, or unusual translations that could distort the image.
- bool usePixelSpace = transformSpace == TransformSpace.Pixel && IsAffineRotationOrSkew(matrix);
-
- // Define an offset size to translate between pixel space and coordinate space.
- // When using pixel space, apply a scaling sensitive offset to translate to discrete pixel coordinates.
- // When not using pixel space, use SizeF.Empty as the offset.
-
- // Compute scaling factors from the matrix
- float scaleX = 1F / new Vector2(matrix.M11, matrix.M21).Length(); // sqrt(M11^2 + M21^2)
- float scaleY = 1F / new Vector2(matrix.M12, matrix.M22).Length(); // sqrt(M12^2 + M22^2)
-
- // Apply the offset relative to the scale
- SizeF offsetSize = usePixelSpace ? new SizeF(scaleX, scaleY) : SizeF.Empty;
-
- // Subtract the offset size to translate to the appropriate space (pixel or coordinate).
- if (TryGetTransformedRectangle(new RectangleF(Point.Empty, size - offsetSize), matrix, out Rectangle bounds))
+ if (TryGetTransformedRectangle(new RectangleF(Point.Empty, size), matrix, out RectangleF bounds))
{
- // Add the offset size back to translate the transformed bounds to the correct space.
- return Size.Ceiling(ConstrainSize(bounds) + offsetSize);
+ return preserveCanvas ? GetPreserveCanvasSize(bounds) : bounds.Size;
}
return size;
@@ -438,30 +456,31 @@ public static Matrix4x4 GetSwizzlerMatrix(T swizzler, Rectangle sourceRectang
swizzler.Transform(new Point(sourceRectangle.Left, sourceRectangle.Top)),
swizzler.Transform(new Point(sourceRectangle.Right, sourceRectangle.Top)),
swizzler.Transform(new Point(sourceRectangle.Right, sourceRectangle.Bottom)),
- swizzler.Transform(new Point(sourceRectangle.Left, sourceRectangle.Bottom)),
- TransformSpace.Pixel);
+ swizzler.Transform(new Point(sourceRectangle.Left, sourceRectangle.Bottom)));
///
/// Returns the size relative to the source for the given transformation matrix.
///
/// The transformation matrix.
- /// The source size.
- /// The to use when calculating the size.
+ /// The original source size.
/// The .
- private static Size GetUnboundedTransformedSize(Matrix3x2 matrix, Size size, TransformSpace transformSpace)
- => GetTransformedSize(matrix, size, transformSpace, false);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static SizeF GetRawTransformedSize(Matrix3x2 matrix, Size size)
+ => GetTransformedSize(matrix, size, false);
///
- /// Returns the size relative to the source for the given transformation matrix.
+ /// Returns the size of the transformed source. When is true,
+ /// the size is expanded to include translation so the full moved content remains visible.
///
/// The transformation matrix.
- /// The source size.
- /// The to use when calculating the size.
- /// Whether to constrain the size to ensure that the dimensions are positive.
- ///
- /// The .
- ///
- private static Size GetTransformedSize(Matrix3x2 matrix, Size size, TransformSpace transformSpace, bool constrain)
+ /// The original source size.
+ ///
+ /// If , expand the size to account for translation (left/up as well as right/down).
+ /// If , return only the transformed span without translation expansion.
+ ///
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static SizeF GetTransformedSize(Matrix3x2 matrix, Size size, bool preserveCanvas)
{
Guard.IsTrue(size.Width > 0 && size.Height > 0, nameof(size), "Source size dimensions cannot be 0!");
@@ -470,21 +489,9 @@ private static Size GetTransformedSize(Matrix3x2 matrix, Size size, TransformSpa
return size;
}
- // Define an offset size to translate between coordinate space and pixel space.
- // Compute scaling factors from the matrix
- SizeF offsetSize = SizeF.Empty;
- if (transformSpace == TransformSpace.Pixel)
- {
- float scaleX = 1F / new Vector2(matrix.M11, matrix.M21).Length(); // sqrt(M11^2 + M21^2)
- float scaleY = 1F / new Vector2(matrix.M12, matrix.M22).Length(); // sqrt(M12^2 + M22^2)
- offsetSize = new SizeF(scaleX, scaleY);
- }
-
- // Subtract the offset size to translate to the pixel space.
- if (TryGetTransformedRectangle(new RectangleF(Point.Empty, size - offsetSize), matrix, out Rectangle bounds))
+ if (TryGetTransformedRectangle(new RectangleF(Point.Empty, size), matrix, out RectangleF bounds))
{
- // Add the offset size back to translate the transformed bounds to the coordinate space.
- return Size.Ceiling((constrain ? ConstrainSize(bounds) : bounds.Size) + offsetSize);
+ return preserveCanvas ? GetPreserveCanvasSize(bounds) : bounds.Size;
}
return size;
@@ -499,7 +506,8 @@ private static Size GetTransformedSize(Matrix3x2 matrix, Size size, TransformSpa
///
/// if the transformation was successful; otherwise, .
///
- private static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix3x2 matrix, out Rectangle bounds)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix3x2 matrix, out RectangleF bounds)
{
if (matrix.IsIdentity || rectangle.Equals(default))
{
@@ -526,7 +534,7 @@ private static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix3x2 m
/// if the transformation was successful; otherwise, .
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix4x4 matrix, out Rectangle bounds)
+ internal static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix4x4 matrix, out RectangleF bounds)
{
if (matrix.IsIdentity || rectangle.Equals(default))
{
@@ -543,15 +551,61 @@ internal static bool TryGetTransformedRectangle(RectangleF rectangle, Matrix4x4
return true;
}
+ ///
+ /// Calculates the size of a destination canvas large enough to contain the full
+ /// transformed content of a source rectangle while preserving any translation offsets.
+ ///
+ ///
+ /// The representing the transformed bounds of the source content
+ /// in destination (output) space.
+ ///
+ ///
+ /// A that describes the canvas dimensions required to fully
+ /// contain the transformed content while accounting for any positive or negative translation.
+ ///
+ ///
+ ///
+ /// This method expands the output canvas to ensure that translated content remains visible.
+ ///
+ ///
+ /// If the transformation produces a positive translation, the method extends the canvas
+ /// on the positive side (right or bottom).
+ /// If the transformation produces a negative translation (the content moves left or up),
+ /// the method extends the canvas on the negative side to include that offset.
+ ///
+ ///
+ /// The result is equivalent to taking the union of:
+ ///
+ /// -
+ /// The original, untransformed rectangle at the origin [0..Width] × [0..Height].
+ ///
+ /// -
+ /// The translated rectangle defined by .
+ ///
+ ///
+ /// This ensures the entire translated image fits within the resulting canvas,
+ /// without trimming any portion caused by translation.
+ ///
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Size ConstrainSize(Rectangle rectangle)
+ private static SizeF GetPreserveCanvasSize(RectangleF rectangle)
{
- // We want to resize the canvas here taking into account any translations.
- int height = rectangle.Top < 0 ? rectangle.Bottom : Math.Max(rectangle.Height, rectangle.Bottom);
- int width = rectangle.Left < 0 ? rectangle.Right : Math.Max(rectangle.Width, rectangle.Right);
-
- // If location in either direction is translated to a negative value equal to or exceeding the
- // dimensions in either direction we need to reassign the dimension.
+ // Compute the required height.
+ // If the top is negative, expand upward by that amount (rectangle.Bottom already includes height).
+ // Otherwise, take the larger of the transformed height or the bottom offset.
+ float height = rectangle.Top < 0
+ ? rectangle.Bottom
+ : MathF.Max(rectangle.Height, rectangle.Bottom);
+
+ // Compute the required width.
+ // If the left is negative, expand leftward by that amount (rectangle.Right already includes width).
+ // Otherwise, take the larger of the transformed width or the right offset.
+ float width = rectangle.Left < 0
+ ? rectangle.Right
+ : MathF.Max(rectangle.Width, rectangle.Right);
+
+ // Guard: if translation exceeds or cancels dimensions,
+ // ensure non-zero positive size using the base rectangle dimensions.
if (height <= 0)
{
height = rectangle.Height;
@@ -562,63 +616,63 @@ private static Size ConstrainSize(Rectangle rectangle)
width = rectangle.Width;
}
- return new Size(width, height);
+ // Return the final size that preserves the full visible region of the transformed content.
+ return new SizeF(width, height);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Rectangle GetBoundingRectangle(Vector2 tl, Vector2 tr, Vector2 bl, Vector2 br)
+ private static RectangleF GetBoundingRectangle(Vector2 tl, Vector2 tr, Vector2 bl, Vector2 br)
{
- // Find the minimum and maximum "corners" based on the given vectors
float left = MathF.Min(tl.X, MathF.Min(tr.X, MathF.Min(bl.X, br.X)));
float top = MathF.Min(tl.Y, MathF.Min(tr.Y, MathF.Min(bl.Y, br.Y)));
float right = MathF.Max(tl.X, MathF.Max(tr.X, MathF.Max(bl.X, br.X)));
float bottom = MathF.Max(tl.Y, MathF.Max(tr.Y, MathF.Max(bl.Y, br.Y)));
- // Clamp the values to the nearest whole pixel.
- return Rectangle.FromLTRB(
- (int)Math.Floor(left),
- (int)Math.Floor(top),
- (int)Math.Ceiling(right),
- (int)Math.Ceiling(bottom));
+ return RectangleF.FromLTRB(left, top, right, bottom);
}
- private static bool IsAffineRotationOrSkew(Matrix4x4 matrix)
+ ///
+ /// Normalizes an affine 2D matrix so that it operates in pixel space.
+ /// Applies the row-vector conjugation T(+0.5,+0.5) * M * T(-0.5,-0.5)
+ /// to align the transform with pixel centers.
+ ///
+ /// The affine matrix.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix3x2 NormalizeToPixel(Matrix3x2 matrix)
{
- const float epsilon = 1e-6f;
+ const float dx = 0.5f, dy = 0.5f;
- // Check if the matrix is affine (last column should be [0, 0, 0, 1])
- if (Math.Abs(matrix.M14) > epsilon ||
- Math.Abs(matrix.M24) > epsilon ||
- Math.Abs(matrix.M34) > epsilon ||
- Math.Abs(matrix.M44 - 1f) > epsilon)
- {
- return false;
- }
-
- // Translation component (M41, m42) are allowed, others are not.
- if (Math.Abs(matrix.M43) > epsilon)
- {
- return false;
- }
-
- // Extract the linear (rotation and skew) part of the matrix
- // Upper-left 3x3 matrix
- float m11 = matrix.M11, m12 = matrix.M12, m13 = matrix.M13;
- float m21 = matrix.M21, m22 = matrix.M22, m23 = matrix.M23;
- float m31 = matrix.M31, m32 = matrix.M32, m33 = matrix.M33;
+ matrix.M31 += (-dx) + ((dx * matrix.M11) + (dy * matrix.M21));
+ matrix.M32 += (-dy) + ((dx * matrix.M12) + (dy * matrix.M22));
+ return matrix;
+ }
- // Compute the determinant of the linear part
- float determinant = (m11 * ((m22 * m33) - (m23 * m32))) -
- (m12 * ((m21 * m33) - (m23 * m31))) +
- (m13 * ((m21 * m32) - (m22 * m31)));
+ ///
+ /// Normalizes a projective 4×4 matrix so that it operates in pixel space.
+ /// Applies the row-vector conjugation T(+0.5,+0.5,0) * M * T(-0.5,-0.5,0)
+ /// to align the transform with pixel centers.
+ ///
+ /// The projective matrix.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4x4 NormalizeToPixel(Matrix4x4 matrix)
+ {
+ const float dx = 0.5f, dy = 0.5f;
- // Check if the determinant is approximately ±1 (no scaling)
- if (Math.Abs(Math.Abs(determinant) - 1f) > epsilon)
+ // Fast path: affine (no perspective)
+ if (matrix.M14 == 0f && matrix.M24 == 0f && matrix.M34 == 0f && matrix.M44 == 1f)
{
- return false;
+ // t' = t + (-d + d·L)
+ matrix.M41 += (-dx) + ((dx * matrix.M11) + (dy * matrix.M21));
+ matrix.M42 += (-dy) + ((dx * matrix.M12) + (dy * matrix.M22));
+ return matrix;
}
- // All checks passed; the matrix represents rotation and/or skew (with possible translation)
- return true;
+ Matrix4x4 tPos = Matrix4x4.Identity;
+ tPos.M41 = dx;
+ tPos.M42 = dy;
+ Matrix4x4 tNeg = Matrix4x4.Identity;
+ tNeg.M41 = -dx;
+ tNeg.M42 = -dy;
+ return tPos * matrix * tNeg;
}
}
diff --git a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
index 82b897ea5d..dc049ef0e5 100644
--- a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
+++ b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
@@ -17,24 +17,9 @@ public class ProjectiveTransformBuilder
/// Initializes a new instance of the class.
///
public ProjectiveTransformBuilder()
- : this(TransformSpace.Pixel)
{
}
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// The to use when applying the projective transform.
- ///
- public ProjectiveTransformBuilder(TransformSpace transformSpace)
- => this.TransformSpace = transformSpace;
-
- ///
- /// Gets the to use when applying the projective transform.
- ///
- public TransformSpace TransformSpace { get; }
-
///
/// Prepends a matrix that performs a tapering projective transform.
///
@@ -69,7 +54,7 @@ public ProjectiveTransformBuilder PrependRotationDegrees(float degrees)
/// The amount of rotation, in radians.
/// The .
public ProjectiveTransformBuilder PrependRotationRadians(float radians)
- => this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace)));
+ => this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationTransformMatrixRadians(radians, size)));
///
/// Prepends a centered rotation matrix using the given rotation in degrees at the given origin.
@@ -87,7 +72,8 @@ internal ProjectiveTransformBuilder PrependRotationDegrees(float degrees, Vector
/// The rotation origin point.
/// The .
internal ProjectiveTransformBuilder PrependRotationRadians(float radians, Vector2 origin)
- => this.PrependMatrix(Matrix4x4.CreateRotationZ(radians, new Vector3(origin, 0)));
+ => this.PrependMatrix(
+ Matrix4x4.CreateRotationZ(radians, new Vector3(origin, 0)));
///
/// Appends a centered rotation matrix using the given rotation in degrees.
@@ -103,7 +89,7 @@ public ProjectiveTransformBuilder AppendRotationDegrees(float degrees)
/// The amount of rotation, in radians.
/// The .
public ProjectiveTransformBuilder AppendRotationRadians(float radians)
- => this.Append(size => new Matrix4x4(TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace)));
+ => this.Append(size => new Matrix4x4(TransformUtils.CreateRotationTransformMatrixRadians(radians, size)));
///
/// Appends a centered rotation matrix using the given rotation in degrees at the given origin.
@@ -187,7 +173,7 @@ internal ProjectiveTransformBuilder PrependSkewDegrees(float degreesX, float deg
/// The Y angle, in radians.
/// The .
public ProjectiveTransformBuilder PrependSkewRadians(float radiansX, float radiansY)
- => this.Prepend(size => new Matrix4x4(TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size, this.TransformSpace)));
+ => this.Prepend(size => new Matrix4x4(TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size)));
///
/// Prepends a skew matrix using the given angles in degrees at the given origin.
@@ -225,7 +211,7 @@ internal ProjectiveTransformBuilder AppendSkewDegrees(float degreesX, float degr
/// The Y angle, in radians.
/// The .
public ProjectiveTransformBuilder AppendSkewRadians(float radiansX, float radiansY)
- => this.Append(size => new Matrix4x4(TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size, this.TransformSpace)));
+ => this.Append(size => new Matrix4x4(TransformUtils.CreateSkewTransformMatrixRadians(radiansX, radiansY, size)));
///
/// Appends a skew matrix using the given angles in degrees at the given origin.
@@ -289,7 +275,11 @@ public ProjectiveTransformBuilder AppendTranslation(Vector2 position)
/// The .
public ProjectiveTransformBuilder PrependQuadDistortion(PointF topLeft, PointF topRight, PointF bottomRight, PointF bottomLeft)
=> this.Prepend(size => TransformUtils.CreateQuadDistortionMatrix(
- new Rectangle(Point.Empty, size), topLeft, topRight, bottomRight, bottomLeft, this.TransformSpace));
+ new Rectangle(Point.Empty, size),
+ topLeft,
+ topRight,
+ bottomRight,
+ bottomLeft));
///
/// Appends a quad distortion matrix using the specified corner points.
@@ -301,7 +291,11 @@ public ProjectiveTransformBuilder PrependQuadDistortion(PointF topLeft, PointF t
/// The .
public ProjectiveTransformBuilder AppendQuadDistortion(PointF topLeft, PointF topRight, PointF bottomRight, PointF bottomLeft)
=> this.Append(size => TransformUtils.CreateQuadDistortionMatrix(
- new Rectangle(Point.Empty, size), topLeft, topRight, bottomRight, bottomLeft, this.TransformSpace));
+ new Rectangle(Point.Empty, size),
+ topLeft,
+ topRight,
+ bottomRight,
+ bottomLeft));
///
/// Prepends a raw matrix.
@@ -383,12 +377,26 @@ public Matrix4x4 BuildMatrix(Rectangle sourceRectangle)
/// for linear transforms.
///
/// The .
- public Size GetTransformedSize(Rectangle sourceRectangle)
+ public SizeF GetTransformedSize(Rectangle sourceRectangle)
{
Matrix4x4 matrix = this.BuildMatrix(sourceRectangle);
- return TransformUtils.GetTransformedSize(matrix, sourceRectangle.Size, this.TransformSpace);
+ return GetTransformedSize(sourceRectangle, matrix);
}
+ ///
+ /// Returns the size of a rectangle large enough to contain the transformed source rectangle.
+ ///
+ /// The rectangle in the source image.
+ /// The transformation matrix.
+ ///
+ /// 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 .
+ internal static SizeF GetTransformedSize(Rectangle sourceRectangle, Matrix4x4 matrix)
+ => TransformUtils.GetRawTransformedSize(matrix, sourceRectangle.Size);
+
private static void CheckDegenerate(Matrix4x4 matrix)
{
if (TransformUtils.IsDegenerate(matrix))
diff --git a/src/ImageSharp/Processing/TransformSpace.cs b/src/ImageSharp/Processing/TransformSpace.cs
deleted file mode 100644
index bca676bd88..0000000000
--- a/src/ImageSharp/Processing/TransformSpace.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-namespace SixLabors.ImageSharp.Processing;
-
-///
-/// Represents the different spaces used in transformation operations.
-///
-public enum TransformSpace
-{
- ///
- /// Coordinate space is a continuous, mathematical grid where objects and positions
- /// are defined with precise, often fractional values. This space allows for fine-grained
- /// transformations like scaling, rotation, and translation with high precision.
- /// In coordinate space, an image can span from (0,0) to (4,4) for a 4x4 image, including the boundaries.
- ///
- Coordinate,
-
- ///
- /// Pixel space is a discrete grid where each position corresponds to a specific pixel on the screen.
- /// In this space, positions are defined by whole numbers, with no fractional values.
- /// A 4x4 image in pixel space covers exactly 4 pixels wide and 4 pixels tall, ranging from (0,0) to (3,3).
- /// Pixel space is used when rendering images to ensure that everything aligns with the actual pixels on the screen.
- ///
- Pixel
-}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
index a7855e23aa..941d78c436 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs
@@ -234,7 +234,23 @@ public void Issue2753(TestImageProvider provider)
image.DebugSave(provider);
Assert.Equal(4, image.Width);
- Assert.Equal(8, image.Height);
+ Assert.Equal(7, image.Height);
+ }
+
+ [Theory]
+ [WithFile(TestImages.Png.Issue3000, PixelTypes.Rgba32, 3, 3)]
+ [WithFile(TestImages.Png.Issue3000, PixelTypes.Rgba32, 4, 4)]
+ public void Issue3000(TestImageProvider provider, float x, float y)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage();
+
+ image.Mutate(c => c
+ .Transform(new AffineTransformBuilder().AppendRotationDegrees(90, new Vector2(x, y))));
+
+ string details = $"p-{x}-{y}";
+ image.DebugSave(provider, testOutputDetails: details);
+ image.CompareToReferenceOutput(ValidatorComparer, provider, testOutputDetails: details);
}
[Theory]
@@ -267,31 +283,41 @@ public void Transform_With_Custom_Dimensions(TestImageProvider p
image.CompareToReferenceOutput(ValidatorComparer, provider, testOutputDetails: radians);
}
- [Fact]
- public void TransformRotationDoesNotOffset()
+ [Theory]
+ [WithSolidFilledImages(100, 100, "DimGray", PixelTypes.Rgba32)]
+ public void TransformRotationDoesNotOffset(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
{
Rgba32 background = Color.DimGray.ToPixel();
- Rgba32 marker = Color.Aqua.ToPixel();
+ TPixel marker = Color.Aqua.ToPixel();
+
+ using Image canvas = provider.GetImage();
- using Image img = new(100, 100, background);
+ using Image img = canvas.Clone();
img[0, 0] = marker;
img.Mutate(c => c.Rotate(180));
Assert.Equal(marker, img[99, 99]);
- using Image img2 = new(100, 100, background);
+ img.DebugSave(provider, "Rotate180");
+
+ using Image img2 = canvas.Clone();
img2[0, 0] = marker;
img2.Mutate(
c =>
c.Transform(new AffineTransformBuilder().AppendRotationDegrees(180), KnownResamplers.NearestNeighbor));
- using Image img3 = new(100, 100, background);
+ img.DebugSave(provider, "AffineRotate180NN");
+
+ using Image img3 = canvas.Clone();
img3[0, 0] = marker;
img3.Mutate(c => c.Transform(new AffineTransformBuilder().AppendRotationDegrees(180)));
+ img3.DebugSave(provider, "AffineRotate180Bicubic");
+
ImageComparer.Exact.VerifySimilarity(img, img2);
ImageComparer.Exact.VerifySimilarity(img, img3);
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs
index 2e580ea9fa..c65f136d66 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs
@@ -249,17 +249,17 @@ public void TransformUpdatesSubject(TestImageProvider provider)
image.Mutate(ctx => ctx.Transform(builder));
// A 180-degree rotation inverts both axes around the image center.
- // The subject location (5, 15) becomes (imageWidth - 5 - 1, imageHeight - 15 - 1) = (94, 84)
+ // The subject location (5, 15) becomes (imageWidth - 5, imageHeight - 15) = (95, 85)
Assert.Equal(
- [94, 84],
+ [95, 85],
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectLocation).Value);
// The subject area is also mirrored around the center.
// New X = imageWidth - originalX - width
// New Y = imageHeight - originalY - height
- // (5, 15, 50, 50) becomes (44, 34, 50, 50)
+ // (5, 15, 50, 50) becomes (45, 35, 50, 50)
Assert.Equal(
- [44, 34, 50, 50],
+ [45, 35, 50, 50],
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectArea).Value);
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
index 1e0e66965a..023d47886d 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
@@ -652,7 +652,7 @@ public void ResizeUpdatesSubject(TestImageProvider provider)
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectLocation).Value);
Assert.Equal(
- [2, 7, 11, 11],
+ [2, 7, 10, 10],
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectArea).Value);
}
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs
index dfa263fec0..5eee7313d9 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs
@@ -55,17 +55,17 @@ public void RotateUpdatesSubject(TestImageProvider provider)
image.Mutate(ctx => ctx.Rotate(180));
// A 180-degree rotation inverts both axes around the image center.
- // The subject location (5, 15) becomes (imageWidth - 5 - 1, imageHeight - 15 - 1) = (94, 84)
+ // The subject location (5, 15) becomes (imageWidth - 5, imageHeight - 15) = (95, 85)
Assert.Equal(
- [94, 84],
+ [95, 85],
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectLocation).Value);
// The subject area is also mirrored around the center.
// New X = imageWidth - originalX - width
// New Y = imageHeight - originalY - height
- // (5, 15, 50, 50) becomes (44, 34, 50, 50)
+ // (5, 15, 50, 50) becomes (45, 35, 50, 50)
Assert.Equal(
- [44, 34, 50, 50],
+ [45, 35, 50, 50],
image.Metadata.ExifProfile.GetValue(ExifTag.SubjectArea).Value);
}
}
diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs
index 5caf071aca..f5aa1715f4 100644
--- a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs
+++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs
@@ -98,7 +98,7 @@ public void AppendRotationDegrees_WithoutSpecificRotationCenter_RotationIsCenter
this.AppendRotationDegrees(builder, degrees);
// TODO: We should also test CreateRotationMatrixDegrees() (and all TransformUtils stuff!) for correctness
- Matrix3x2 matrix = TransformUtils.CreateRotationTransformMatrixDegrees(degrees, size, TransformSpace.Pixel);
+ Matrix3x2 matrix = TransformUtils.CreateRotationTransformMatrixDegrees(degrees, size);
Vector2 position = new(x, y);
Vector2 expected = Vector2.Transform(position, matrix);
@@ -152,7 +152,7 @@ public void AppendSkewDegrees_WithoutSpecificSkewCenter_SkewIsCenteredAroundImag
this.AppendSkewDegrees(builder, degreesX, degreesY);
- Matrix3x2 matrix = TransformUtils.CreateSkewTransformMatrixDegrees(degreesX, degreesY, size, TransformSpace.Pixel);
+ Matrix3x2 matrix = TransformUtils.CreateSkewTransformMatrixDegrees(degreesX, degreesY, size);
Vector2 position = new(x, y);
Vector2 expected = Vector2.Transform(position, matrix);
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index af6148c873..76475031cc 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -163,6 +163,9 @@ public static class Png
// Issue 2924: https://github.com/SixLabors/ImageSharp/issues/2924
public const string Issue2924 = "Png/issues/Issue_2924.png";
+ // Issue 3000: htps://github.com/SixLabors/ImageSharp/issues/3000
+ public const string Issue3000 = "Png/issues/issue_3000.png";
+
public static class Bad
{
public const string MissingDataChunk = "Png/xdtn0g01.png";
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-3-3.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-3-3.png
new file mode 100644
index 0000000000..385ac042c5
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-3-3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d75205909d532dc98da52389c804ff99cb3b796b5657afb521659fe221c2b8f0
+size 122
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-4-4.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-4-4.png
new file mode 100644
index 0000000000..ef4aa03b92
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Issue3000_Rgba32_issue_3000_p-4-4.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a75beaec77378de4abb09317afa56b8e99ecba0d1c8571cad31aa790afb1a687
+size 123
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
index 53ac0ff89f..7fad1fcba1 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bbe1ffaf7b801fd92724438cc810fd0c5506e0a907b970c4f0bf5bec3627ca2a
-size 551
+oid sha256:60b050406fda4ff347660e71cb28a9dfceb4b39532f62ee96cb61d2671d3cf00
+size 340
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48__original.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48__original.png
new file mode 100644
index 0000000000..0d610ae036
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48__original.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:74bf3b8655c7548f28c25b1e467992f691dc429f4b06e85cfd04a3b541825811
+size 478
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
index 2480164d60..b22cbb0196 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b45933471a1af1b6d4112240e1bc6b6187065a872043ddbf917200ce9e8cc84b
-size 371
+oid sha256:fbfb3143d96070c58c949e8d1e8d9ddbcf1e7863514489ea2defc65863c84e73
+size 276
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png
index da8e446c02..df64eea180 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b66a5f9d8a7f3f2a78b868bec6c7d1deea927b82d81aa6d1677e0461a3920dc9
-size 3800
+oid sha256:120b661bef4adac64d362d8c987b3427cd8140ccac7404d09a16765ba1199434
+size 5191
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png
index 4c45ba8c6c..b1e8764c1c 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d5fdc46ee866e088e0ec3221145a3d2d954a0bcb6d25cbb4d538978272f34949
-size 4871
+oid sha256:0d668ebe5f8857fd21d7eb9ae86860751a6f3061f6c9f76705ff49216dc07870
+size 6215
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png
index 480c07da48..6067f0ccc0 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5ae57ca0658b1ffa7aca9031f4ec065ab5a9813fb8a9c5acd221526df6a4f729
-size 9747
+oid sha256:2fb676b3af585e7cbe2efdb893157d5f4e152cf810d0693cafb81596e941e121
+size 9697
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png
index d1ea99cf90..69f862a5a9 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0fced9def2b41cbbf215a49ea6ef6baf4c3c041fd180671eb209db5c6e7177e5
-size 10470
+oid sha256:afe7ddbff155b918a4eff91af31e01100355c146cb9c8a12ab2496da8b22821d
+size 10446
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png
index 227f546515..5b88ba5088 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1e4cc16c2f1b439f8780dead04db01fed95f8e20b68270ae8e7a988af999e3db
-size 10561
+oid sha256:ad76301984e5b54eae374adfe130693667053fbed181847b4c68688fb74c9818
+size 10518
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png
index b93742a858..7f08d0dfdf 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:06e3966550f1c3ae72796e5522f7829cf1f86daca469c479acf49e6fae72e3d0
-size 13227
+oid sha256:fbd57af1fa982f9090f57d820a9b927f894914e5f54774e9cd6fdcfe14e5f761
+size 13139
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png
index 57c3b02ba7..2d4ad649fe 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8ce5fefe04cc2a036fddcfcf038901a7a09b4ea5d0621a1e0d3abc8430953ae3
-size 20778
+oid sha256:c4bbc28c203550baf885cefba95c48a3f91dfb5242c09acbf3a8509b7258048e
+size 20768
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png
index b3bfc7ee51..08182dcfbd 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b653c0fe761d351cb15b09f35da578a954d103dea7507e2c1d7c4ebf3bdac49a
-size 10943
+oid sha256:566e85b1a527f48c953bcc7bc6c58ebd1fe0b14972c38edd596b025e0dd48624
+size 10940
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
index a295c016d5..392d3462f6 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3a17bb1653cc6d6ecc292ce0670c651bfea032f61c6a0e84636205bde53a86f8
-size 13536
+oid sha256:aa5b0d5de93f26c0a7a03b57a00d4a49cda62f4a4b98b6d374261467c03a8357
+size 13500
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
index 63214687d5..56f2a31278 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b8970378312c0d479d618e4d5b8da54175c127db517fbe54f9057188d02cc735
-size 4165
+oid sha256:62267d8d56af3e1452f0e25144f2cfe352b88def98af28e819a3a6982040a4ca
+size 4102
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
index a295c016d5..5919cce39e 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3a17bb1653cc6d6ecc292ce0670c651bfea032f61c6a0e84636205bde53a86f8
-size 13536
+oid sha256:878d5c53b84af4d133825206a327fd4cd02a43831ecabf5c61c5d89181c5a107
+size 13499
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
index ef37b3e2d6..fa01f13cc1 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9bbf7ef00f98b410f309b3bf70ce87d3c6455666a26e89cd004744145a10408a
-size 12559
+oid sha256:f0aa3c19852632e603ec425aeecc5243d4c6c24a1ac6e3906d29913bf7ead2df
+size 12535
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
index 93a0ce6c54..98ad27d78f 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7f9ab86abad276d58bb029bd8e2c2aaffac5618322788cb3619577c7643e10d2
-size 14223
+oid sha256:ec648c2e8006d478ace4a78d2434a4ef7f10d4a3502468cd8b9e2b1f154620b6
+size 14278
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
index c2ca6bf57b..feb217ee9f 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:05c4dc9af1fef422fd5ada2fa1459c26253e0fb5e5a13226fa2e7445ece32272
-size 17927
+oid sha256:6cb06152d5a0765ad86e8005d6ddac469914ccced89d5ee37d77e7d030b97c9e
+size 17281
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
index ade9a1ccd8..fd1cf7e774 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:82b47e1cad2eea417b99a2e4b68a5ba1a6cd6703f360e8402f3dca8b92373ecc
-size 18945
+oid sha256:38ea8596a682be0075bb31ed176b1fe04b518eb887235d551a574e338d45880b
+size 18869
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
index cf04e20363..6194834211 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b15ce5a201ee6b946de485a58d3d8e779b6841457e096b2bd7a92968a122f9af
-size 20844
+oid sha256:965f42f021c63a0f2ccc691723c4ad7f92119294aec407c7ffd46a6238c8f268
+size 20792
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
index 6be0fc0ff8..7201a5f159 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a1622a48b3f4790d66b229ed29acd18504cedf68d0a548832665c28d47ea663b
-size 13857
+oid sha256:86f1b9e8f1e38070ce862d87c927313904ceaa9e6080f5acead90e82d164738c
+size 13879
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
index 0064e973ff..77c61443b3 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:74df7b82e2148cfc8dae7e05c96009c0d70c09bf39cdc5ef9d727063d2a8cb3f
-size 4154
+oid sha256:270f9c2bf5d15fcb21796b3b9eb393e0cc00d9c337036637295ad1efb56781b1
+size 4114
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
index 5dd0c52255..22dc949c3c 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cc740ccd76910e384ad84a780591652ac7ee0ea30abf7fd7f5b146f8ff380f07
-size 13991
+oid sha256:d413162a83c223124a2f29f8154e4bdc08d94bd3e15569ec6cffaa13bdda72c8
+size 13953
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
index a6e120e904..3d86b73ab8 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ccdc54e814604d4d339f6083091abf852aae65052ceb731af998208faddb5b0b
-size 13744
+oid sha256:941ea7b4d1f2c187f58920546e2f19fc275505929439cc389edcc59e652e8787
+size 13777
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
index d32c11d44c..060fdc8092 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cd24e0a52c7743ab7d3ed255e3757c2d5495b3f56198556a157df589b1fb67ca
-size 14889
+oid sha256:cc5e6a607ef2343cb74c5227dbc7861840db956951f1fc4703fe53dbccda0974
+size 14808
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
index 72782b0b99..5240721602 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:878f1aab39b0b2405498c24146b8f81248b37b974e5ea7882e96174a034b645f
-size 12374
+oid sha256:2ac06a9ba2b2c8bef7e0117ac52fbb790101c0f89313dc49feb1f5a1d929ab02
+size 12381
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
index 6cedab729b..669aeba9ab 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dcc2bf4f7e0ab3d56ee71ac1e1855dababeb2e4ec167fd5dc264efdc9e727328
-size 17027
+oid sha256:ad0f483fa7fda620860858c4f330ba914480fba15d70b408fb1aa3fed52dbfc1
+size 16839
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
index 7368a3b007..438450e535 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_0.0001.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6c733878f4c0cc6075a01fbe7cb471f8b3e91c2c5eaf89309ea3c073d9cc4921
-size 854
+oid sha256:ba501a7fc32a68f8989965aa6457b3860ec42947e2bcd4526c7570ff743f38fc
+size 841
diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
index da66b26768..f7f2101d78 100644
--- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
+++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:af872886136893938aee82b1ac73e7a1820666a9a5f4bbf34159c09b3283169a
-size 5520
+oid sha256:8265c5b2e8edd5eaf0aeeccf86cac486e7beec581e696d3b4f4cfee8f4be9b2b
+size 5554
diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png
index 7e693a5839..3692f1a1e5 100644
--- a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png
+++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0ba180567e820b145a13c9b26db9c777e95126adfe8e8cacec0ffe1060dcfe8d
-size 184124
+oid sha256:7f8a4db4facce1d68b363a3b59ea40c9da9fa3c989c736d97a703c84d8230660
+size 184595
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=-50, Y=-50 ]-PointF [ X=200, Y=-50 ]-PointF [ X=200, Y=200 ]-PointF [ X=-50, Y=200 ].png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=-50, Y=-50 ]-PointF [ X=200, Y=-50 ]-PointF [ X=200, Y=200 ]-PointF [ X=-50, Y=200 ].png
index 38c603855c..fc2f4b0c6b 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=-50, Y=-50 ]-PointF [ X=200, Y=-50 ]-PointF [ X=200, Y=200 ]-PointF [ X=-50, Y=200 ].png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=-50, Y=-50 ]-PointF [ X=200, Y=-50 ]-PointF [ X=200, Y=200 ]-PointF [ X=-50, Y=200 ].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:abce6af307a81a8ebac8e502142b00b2615403b5570c8dbe7b6895cfdd1a6d60
-size 66879
+oid sha256:ac986987f25d25ab964a5bef710fe81166cb643d85511906218b4f0e72e9e840
+size 30532
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=0, Y=0 ]-PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ].png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=0, Y=0 ]-PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ].png
index f7ea0d0060..e0357c3f1a 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=0, Y=0 ]-PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ].png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=0, Y=0 ]-PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d4cda265a50aa26711efafdbcd947c9a01eff872611df5298920583f9a3d4224
-size 26458
+oid sha256:e0ada2a4d32a3a757b803dbf08148f113f5d358b31af79a77e97c660ce96c302
+size 1608
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ]-PointF [ X=0, Y=0 ].png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ]-PointF [ X=0, Y=0 ].png
index 78c37cc448..18d91fe298 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ]-PointF [ X=0, Y=0 ].png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=150, Y=0 ]-PointF [ X=150, Y=150 ]-PointF [ X=0, Y=150 ]-PointF [ X=0, Y=0 ].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:278a488a858b8eda141493fe00c617eb1f664196853da8341d7e5b7f231ddce4
-size 24645
+oid sha256:ffc30373989ec6857797b460931f011b30baaec633b095b6fc3d8fd5d43c77ec
+size 2467
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=25, Y=50 ]-PointF [ X=210, Y=25 ]-PointF [ X=140, Y=210 ]-PointF [ X=15, Y=125 ].png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=25, Y=50 ]-PointF [ X=210, Y=25 ]-PointF [ X=140, Y=210 ]-PointF [ X=15, Y=125 ].png
index b4740828d4..c1b6694f55 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=25, Y=50 ]-PointF [ X=210, Y=25 ]-PointF [ X=140, Y=210 ]-PointF [ X=15, Y=125 ].png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithQuadDistortion_Rgba32_TestPattern150x150_PointF [ X=25, Y=50 ]-PointF [ X=210, Y=25 ]-PointF [ X=140, Y=210 ]-PointF [ X=15, Y=125 ].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e03e79e6fab3a9e43041e54640a04c7cc3677709e7d879f9f410cf8afc7547a7
-size 42691
+oid sha256:9828ef0faf1a6709673cfe39028ed4202920d346bcc172bda6683bb3d1d0a7a3
+size 36577
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
index 3826753d53..a515475c9d 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:543dbf5376386bf518830850645d69934e2ca17ab208ce3fd5274a6a172f5206
-size 10951
+oid sha256:6bff913e6e67129325203fae91278ca17407b10d99c4e4f571e6cfe3b5b7f93c
+size 10889
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
index f9aa1ffe03..779e437ffd 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0d0cf291ebf5d8cebab1cd76e2830e5e2d2e0d9a050f7187da72680ead39110c
-size 2757
+oid sha256:54b761b76d03216e7aa6238eee92755c03f7b016bffd1400be66ecf136b29c26
+size 2747
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
index 3826753d53..e165b5f3c2 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:543dbf5376386bf518830850645d69934e2ca17ab208ce3fd5274a6a172f5206
-size 10951
+oid sha256:16da371a29269dade522b3d602beee8f769723c5712a348d960805b75619376d
+size 10889
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
index 2f9109ba38..7d420da8cd 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:57698b6666029a55edf8bd35a7ba96f68d224988cf01308a3af1c6606ae9d0b1
-size 10174
+oid sha256:b25b190603828131be8d82a27e019353c9bf80dcb38536e325abc5aa065762ed
+size 10230
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
index 7dfec78983..96e71e12ec 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fc7c9da04142a679887c714c43f1838eba0092a869140d234fce3412673207c6
-size 13575
+oid sha256:0cc07a20532c52151388c42d7add4f9749913c4dd7629253400a51d40760df23
+size 13566
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
index 6e3b97f2df..5e04f3fe3e 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d8b973f41f8afa39b94c71b307b7eb393953e2d083d56e1f0e8f43d6ab1f342a
-size 16821
+oid sha256:64aae32ec91233b6a139d2f515db4a3e609fa3ab6c660cb53b05d672e7f70e6f
+size 16795
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
index 6986c03912..8206fbdbe8 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:122c1501e09516244f0db36e1cca373ff68514a18e84f57ed3072d52d6112e36
-size 17022
+oid sha256:c6167a1fb585b49167f4c8fa1f19111f10c825ea7d41ae4e266680d22b2bb28e
+size 17094
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
index 76b53fabfb..76aaf324ae 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:12181516bce69c9302f15bba928fd530796449599cb9744a2411cc796788ee3b
-size 18066
+oid sha256:131e831cc2e2d8eb4f5860d0e685b31006ab846433e38440b6a85a445aed1a12
+size 17890
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
index ae4242a42b..10301fd320 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1eb5accc5ada5b963ecef6ac15bfb1845f481e51aef63e06a522ea73bbeab945
-size 11194
+oid sha256:aedcc9342e0b37d60759330f62db446646c31da172e21d931ee8e8451ee720ae
+size 11193
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
index efb6a2deed..1f736d0402 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0418f0ea38ec19b407f2b5046d7ff0ed207189ad71db1e50e82c419d83620543
-size 2759
+oid sha256:34f21056cac1ec3f1bd37a6c50466210e7ca7d8263963d2c503535b40e5b31d8
+size 2752
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
index 976be43a3b..b5269595c5 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1233a9ab2c4b0b17b0248c3d40050c466330c22095287dfbdb8bf7dfbda4ff1f
-size 11212
+oid sha256:b4e0cbe71672de45880111fb45c7b544203f67154060fa0707ba9216dfd6d883
+size 11217
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
index 04fb2e87e0..81a20c24a6 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e2912d4e42c7b76d9ff48a49921d6472e351662597d69b88bc3708683c7933e3
-size 11221
+oid sha256:e8208cf34114bc87c6244f83a73e7c9dd4455da2fb6d25c34e32ed2fef3cfc9a
+size 11214
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
index b35d68aaf8..4edc410d90 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:51b05c38647e0c1d88cc722e4109a882305073a065d2a27ccd3bee82f727127d
-size 11775
+oid sha256:c4ee4328adcc71b1d9b3786ab2c03906aa725fefadd1d521206d5a04af421d8d
+size 11711
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
index 64b9c6aba4..f5877639e0 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b260e816b23a43d7efb7507897ba2f5dbb6a596dd67a5abd4c9a0c005e926ee0
-size 9748
+oid sha256:fbc694ac18a702c127c588bb9184bcc39a01c1b8be5ceecadeaab4477260afec
+size 9984
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
index 29b95bf525..49633ed225 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:50b03d627bb53048f5e56380500f116da4c503f5bb6a1b1d3c0d67ee4256d8f6
-size 15977
+oid sha256:8e85f331d7c4304fcd8ea8788da04982d9a5e43951be642bd7dbacd8907c3151
+size 15784
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png
index 54dca26397..65e75b83eb 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:96454548849147d7c7f0ca507c8521a7d5eaa7771f9f383cc836858870b52c57
-size 280
+oid sha256:92153056f19a20cc1d6ff65dd36ffd215eb50509cc3544e338e76c8d5665fb27
+size 278
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png
index 41f94c9c7b..7a9f2794cc 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e94d224fdb284b6f1ba21b8caa66174edd7e6a3027f9dd03f4757e08296e6508
-size 212
+oid sha256:0db75a869ae36fbca7f57daa4495f2c16050b226474d203aba98cb8e0766d3fb
+size 249
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png
index 49cd1c8375..4f01d8c13f 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d1162be9fa1f31bee8d3cba05c1422a1945621a412be11cce13d376efd5c679c
-size 173
+oid sha256:09a80b11d888da121313d5f00ab0ec79ccf7bc49800135aa5eb411bd15fc6b86
+size 204
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png
index 59f928178a..8985e64760 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0ed262e9b885af773a4a40a4506e678630670e208bf7f9ec10307e943b166bed
-size 258
+oid sha256:1ff446c4bb62d4492fc561a9dd48c4c0d95d8f4bcd9bbadf1675b2621baf9fa1
+size 212
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png
index 57ee3dc2ff..1f9f0557b1 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3a24f2cfc225d01294b8bbc5ca7d7f1738fb0b79217046eb9edf04e4c4c01851
-size 201
+oid sha256:2d76e8055ddbdaaa8f21117ab5e06d3e7d0f5da9d21dd2a992d82e284f028606
+size 235
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png
index 7e47f43ff9..c8c5696b1f 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:938186fb3d0f468176988a9530efd22e66241a1361fff027005ec8a8ae323ff3
-size 197
+oid sha256:c7e594fd12ea7863d297d66852d3f80d5d3645636cdd39611c7b6fae068a6dc9
+size 230
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png
index 0f756e7813..434457ffc3 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4bc4b8ea7e7f10676d8de612fe6bc5144e100b95ff3fe7a1e3d4066a7684ce4d
-size 239
+oid sha256:50f7f407d040b1071f7f6fbad96d6cfb2907d87060c671e74f6122ac5d381c30
+size 208
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png
index b2d420886b..d3810b9d61 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:345337f7dffa48d95251503ee2ae8e91db98b5cbe06b579d73c38a018c781544
-size 182
+oid sha256:f305e35f0f4fac1c099b5d9f0b2775c1bb17f382aba13a068dedff45eda4632d
+size 215
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png
index 4f0ad9d045..74d204d7ce 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:de4e2b71dade9dfb750a2c614a684963d6962958db79145c87fd23d9f0f8c005
-size 180
+oid sha256:c41784431d5a50746f66b3c34e966cb21fa8a088de797825633349cb077b4f97
+size 212
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png
index 78bdb8bbbe..308fe34546 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8d8b651663366e7543211635f337c229e2f88f1142886ea3a9b69587daaada97
-size 288
+oid sha256:7a6b2c8e072993c00a96692f10c7ebe6fcc6f4cfdcb9dff2d0aa6c65db54e1c4
+size 267
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png
index 7015a05571..6111bcae16 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8ab8df31f1716c05bb8687f79c7d1154f6cc6f65e3917abe60ecc42d0df173dc
-size 215
+oid sha256:018fe6af5dd7ed2edd163bf3da5e22f8333d3e3287629a2065ebfd15b7a2a8b3
+size 256
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png
index 67a765e8db..a0935a1ce6 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1a1671da9ea7702a37a866fabfb3ca0d746233ee108594198f23cb563af43ae6
-size 180
+oid sha256:530501bed8301799b68ba3dc8d50c877ed3f58073ab1a8a283e8f776e761cd28
+size 200
diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
index 4b2bb99d96..81863d3ef5 100644
--- a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
+++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_With_Custom_Dimensions_Rgba32_TestPattern100x100_57.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1e7dedec16ccd66543a1d44052a104957ba62099ba2f2ccc72285c233c2ae3fa
-size 4411
+oid sha256:73a18d217d0db5e6ed55cbf52801b7f083e083ca2f0a6ac20d320fd29961e6e0
+size 4399
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png
index 65bb77977b..c8b2ee0ce8 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3594547265b23603b1a76ff6bc6f0eab4af55d6e0070e53356123dfc7ae256f8
-size 9034
+oid sha256:881daeef5b8db99af8b89e7d4e968fb4c43e13c904e936aefa1d0156b767803e
+size 9051
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png
index 7c54b1b074..ccd3d8fa5b 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5ae9ef073f3338b71d2a40fcf2e89d9b6ab62204d6de9b6a1f75f4705ee197f0
-size 10704
+oid sha256:86032d5b7e49574655c1cd54886ac57d6385714481ba6bd72176d858f884cd1a
+size 10720
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png
index b6e930224e..30a81a5b98 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:994dda7da034595aa77d107652bea06c86077d24ef8a6883b18f1f509bb19928
-size 8906
+oid sha256:cb823498eacf5bab12f7607d230523a3488e26fcc10fe1b3ab51de900a9dff97
+size 8835
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png
index d1ea99cf90..69f862a5a9 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0fced9def2b41cbbf215a49ea6ef6baf4c3c041fd180671eb209db5c6e7177e5
-size 10470
+oid sha256:afe7ddbff155b918a4eff91af31e01100355c146cb9c8a12ab2496da8b22821d
+size 10446
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png
index 2f3f0f17fe..b2f18f8553 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:29c5f48f1ece0b12854b4c44fba84fdfc9ac5751cdf564a32478dcdaed43b2a4
-size 9798
+oid sha256:be885eca2d9771be335a29d3da533a17376efa4c563996ac4cb37138fd1899eb
+size 9826
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png
index 5242a9d985..39c4304bed 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c7de58474c3f386c4ec31a9088d561a513f82c08d1157132d735169b847b9680
-size 11579
+oid sha256:afea3d7ec03c945d695b3cd85e9ea1d79cb35745256efe1e32273eb08789e5ce
+size 11476
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png
index 2af9d2fc27..e98d3115fa 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3ef9b7051d7a5733dfe2534fddefdc28dfbc49d087355f46c4d945b04f0e3936
-size 9672
+oid sha256:096eba716663179933fe6eb526822ac9dedf83c3633d43df328ed33fb16900f6
+size 9687
diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png
index 83c02764fa..380b4b7d58 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:825770c9b2e9f265d834eab6b40604df5508bf9bc5b4f82f5d3effd6d5a26935
-size 11434
+oid sha256:c7367063704e10827bb81f46ebb56b6fe87a816eb8ec258ca95d8e26d9276f0f
+size 11408
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png
index d6dba3f889..e8822425d5 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1e283463b0f450dd72cf303acccf3dd1ff7a31fe401ff0f288d67c4baefca240
-size 8742
+oid sha256:37acdbbcebe56ab98e17b025312e5860c471d807603c2ce6f4a50fd5f219c0f7
+size 8732
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png
index 76bb244d52..0a798ce06a 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:485d9d9ef955a04af43d17e6bc3952e9bf65a9752b6cf8ba9cbbe8f772f05a18
-size 8995
+oid sha256:722d191e930331e296a548641a80ac163430bdb4017e3d68e4638fbb1d6ed45c
+size 9021
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png
index c1c1d814fd..8d4d2fd9bb 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d3d749ac365764051ea16bc39d1aff84c06faf282359805b58bb97c9eed7f0bb
-size 6400
+oid sha256:ce2bbe927b718a1b4de05b2baad7016b69490d1b5dfb085420192b7ac6c0ec5d
+size 6367
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png
index 27608881ed..2d5fd9e9fc 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8d82f2a15502b0a29aa4df1077ec90c88f9211f283fdc0edd7b059ed9b387441
-size 6334
+oid sha256:d79a7044e95a1ca032124366e4705bd93a866609547ebb489ff7d2228547cea5
+size 6330
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png
index 340455428a..a9de3011d3 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8e8afa56c5abb0e4b5895f35415db1178d041120d9f8306902f554cfaaada88d
-size 26540
+oid sha256:677e4419a1cac8692da2d852f6e169c4a66ef8f164fffa65550fccb71bb54563
+size 26606
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png
index 9ef7866924..2ae230ac52 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a2c174ef54b68f025352e25800f655fe3b94a0d3f75cb48bd2ac0e8d6931faf8
-size 24827
+oid sha256:0f700e854d2d4ee9c12150ef300e0041fa4706ae595eeea6869894a1e2947eaf
+size 24963
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png
index 14f7748537..63f5f99595 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6b56ceae2f350a1402beecc5b5e2930be1011a95fbf224cccf73b96f3931b646
-size 26531
+oid sha256:965248b773ea4b3f8e870ff598ccf88784dd700d9aa063b70b0146a00fc806bc
+size 26613
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png
index c8204eacf3..bf1e063323 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:049ee7fc2bb758609a64149c338bfae2eab44755f53e6b7c25a5e8b8725ed8ac
-size 24416
+oid sha256:cd8e29141de12f1c1a2b3fb057a58b5a017b6db3498023a8f77dc8ac02d7845c
+size 24396
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png
index 2bc57092a2..c903716e7d 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:72c487a2fa3d608021b26a4d6b4517f8548fdcfc62fbafdd8649015dbec8ff87
-size 26504
+oid sha256:a28ac3e9bd2edc2aa7163275006f701672cd7f0b92454a0453a6e73387c70138
+size 26611
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png
index fee364e217..5749ec1ac5 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:099733c9d4490c86cfbb10a016e2dd073539a95f9d5ff9018cf9b5be5404fa13
-size 33435
+oid sha256:2a57780c4145cf1eef6028d7e58ef94ab6d47f80a024f43fe98297f2d398a7fc
+size 33409
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png
index 30325ccc6f..5f98b41849 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:27f2a2b21f8ae878e15120ea5a4a983bde7984b3468dc8426055885efc278fe6
-size 35547
+oid sha256:129f1770502c71fcbe67da35a6966a4c72e4d17ee70a8e951a5229db99d03089
+size 35607
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png
index ff81256a70..979b0366a9 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6b5cbe60e26e123e5a5cdf5a4e88305340f76d32a9c64a220c1fa7512f84e786
-size 39442
+oid sha256:0b7a58c5219ce2b6c91f98b7a75a9c89292e69d816451425b9b829d6a2b1711c
+size 39420
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png
index 263dd7426d..6cfbcee615 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:102cceb79acb1dfd7ec8887b4906e33456c774d48320d1624b3c73975d26f145
-size 25981
+oid sha256:b80944705b204ab37b1a1a0b7d0705fba4f4eae4ea9453ae8ed0e39104765ee9
+size 25836
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png
index 9ef7866924..2ae230ac52 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a2c174ef54b68f025352e25800f655fe3b94a0d3f75cb48bd2ac0e8d6931faf8
-size 24827
+oid sha256:0f700e854d2d4ee9c12150ef300e0041fa4706ae595eeea6869894a1e2947eaf
+size 24963
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png
index 85bbd5ec38..8aeed9c8db 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e61629aeefac7e0a1a6b46b44ad86ed4a5ba0908bb3febc18bb5f9f3ded1c08d
-size 25751
+oid sha256:314e15b8d690b17aa67ee856bcaf55afc62ce86c1b1d86b0f17dffe8739a2d17
+size 25739
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png
index f200a5f955..e7e2c554bc 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:45b1b48e1df393f4c435189c71a6bd3bccfe7a055d76d414a8d0c009b59fa0a0
-size 26145
+oid sha256:abf063ddd974a8eef6b24da9e58a10143d9fefa29369b11f7b27685312a0c74b
+size 26084
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png
index 434bb32a81..0d11b5565a 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d6d186f9e547f658b719bc033e3b110d64cf2a02caecc510d4e2f88359e69746
-size 24176
+oid sha256:f417e1771b2a367f857888ae90bd75f9922d9e5fc8826009ded592d9da010a44
+size 24155
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png
index e3be1ffe5a..0f305ddd3c 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:339b3299984f1450f1a8200e487964c0338b511b82e459d67a3583d0bd46b805
-size 24013
+oid sha256:6aebe33dad1ea3a709f54f234cb779956f5b561a9a5ecf23a95e7ec42d91c535
+size 23905
diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png
index 7dbeeaf357..835d729076 100644
--- a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png
+++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5335c6184829fdc405475bd34d2fae60cf6d5ae050b4d671ac5dd25242ff1368
-size 31888
+oid sha256:bb7684478edd471057076a408c6b32102838db466476929ee58e248f5c20a2b2
+size 31872
diff --git a/tests/Images/Input/Png/issues/issue_3000.png b/tests/Images/Input/Png/issues/issue_3000.png
new file mode 100644
index 0000000000..d7d7ad4c63
--- /dev/null
+++ b/tests/Images/Input/Png/issues/issue_3000.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f33e2f343140b01d9c5c913f4ea695748e3a93df145bc0bf2f73763f2d24cadc
+size 385