|
|
|
@ -1,6 +1,7 @@ |
|
|
|
// Copyright (c) Six Labors and contributors.
|
|
|
|
// Licensed under the Apache License, Version 2.0.
|
|
|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Numerics; |
|
|
|
using SixLabors.ImageSharp.Processing.Processors.Transforms; |
|
|
|
@ -13,34 +14,7 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// </summary>
|
|
|
|
public class ProjectiveTransformBuilder |
|
|
|
{ |
|
|
|
private readonly List<Matrix4x4> matrices = new List<Matrix4x4>(); |
|
|
|
private Rectangle sourceRectangle; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="ProjectiveTransformBuilder"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="sourceSize">The source image size.</param>
|
|
|
|
public ProjectiveTransformBuilder(Size sourceSize) |
|
|
|
: this(new Rectangle(Point.Empty, sourceSize)) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="ProjectiveTransformBuilder"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="sourceRectangle">The source rectangle.</param>
|
|
|
|
public ProjectiveTransformBuilder(Rectangle sourceRectangle) |
|
|
|
{ |
|
|
|
Guard.MustBeGreaterThan(sourceRectangle.Width, 0, nameof(sourceRectangle)); |
|
|
|
Guard.MustBeGreaterThan(sourceRectangle.Height, 0, nameof(sourceRectangle)); |
|
|
|
|
|
|
|
this.sourceRectangle = sourceRectangle; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the source image size.
|
|
|
|
/// </summary>
|
|
|
|
internal Size Size => this.sourceRectangle.Size; |
|
|
|
private readonly List<Func<Size, Matrix4x4>> matrixFactories = new List<Func<Size, Matrix4x4>>(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a matrix that performs a tapering projective transform.
|
|
|
|
@ -50,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// <param name="fraction">The amount to taper.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependTaper(TaperSide side, TaperCorner corner, float fraction) |
|
|
|
=> this.PrependMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction)); |
|
|
|
=> this.Prepend(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a matrix that performs a tapering projective transform.
|
|
|
|
@ -60,7 +34,15 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// <param name="fraction">The amount to taper.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendTaper(TaperSide side, TaperCorner corner, float fraction) |
|
|
|
=> this.AppendMatrix(TransformUtils.CreateTaperMatrix(this.Size, side, corner, fraction)); |
|
|
|
=> this.Append(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a centered rotation matrix using the given rotation in degrees.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependRotationDegrees(float degrees) |
|
|
|
=> this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a centered rotation matrix using the given rotation in radians.
|
|
|
|
@ -68,33 +50,32 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// <param name="radians">The amount of rotation, in radians.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependRotationRadians(float radians) |
|
|
|
{ |
|
|
|
var m = new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, this.Size)); |
|
|
|
return this.PrependMatrix(m); |
|
|
|
} |
|
|
|
=> this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a centered rotation matrix using the given rotation in radians.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="radians">The amount of rotation, in radians.</param>
|
|
|
|
/// <param name="centerPoint">The rotation center.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendRotationRadians(float radians) |
|
|
|
{ |
|
|
|
var m = new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, this.Size)); |
|
|
|
return this.AppendMatrix(m); |
|
|
|
} |
|
|
|
internal ProjectiveTransformBuilder PrependRotationRadians(float radians, Vector2 centerPoint) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a centered rotation matrix using the given rotation in degrees.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendRotationDegrees(float degrees) |
|
|
|
=> this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a centered rotation matrix using the given rotation in radians.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="radians">The amount of rotation, in radians.</param>
|
|
|
|
/// <param name="centerPoint">The rotation center.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
internal ProjectiveTransformBuilder PrependRotationRadians(float radians, Vector2 centerPoint) |
|
|
|
{ |
|
|
|
var m = Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0)); |
|
|
|
return this.PrependMatrix(m); |
|
|
|
} |
|
|
|
public ProjectiveTransformBuilder AppendRotationRadians(float radians) |
|
|
|
=> this.Append(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a centered rotation matrix using the given rotation in radians.
|
|
|
|
@ -103,80 +84,69 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// <param name="centerPoint">The rotation center.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
internal ProjectiveTransformBuilder AppendRotationRadians(float radians, Vector2 centerPoint) |
|
|
|
{ |
|
|
|
var m = Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0)); |
|
|
|
return this.AppendMatrix(m); |
|
|
|
} |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateRotationZ(radians, new Vector3(centerPoint, 0))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a centered rotation matrix using the given rotation in degrees.
|
|
|
|
/// Prepends a scale matrix from the given uniform scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependCenteredRotationDegrees(float degrees) |
|
|
|
=> this.PrependRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); |
|
|
|
/// <param name="scale">The uniform scale.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(float scale) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateScale(scale)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a centered rotation matrix using the given rotation in degrees.
|
|
|
|
/// Prepends a scale matrix from the given vector scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendRotationDegrees(float degrees) |
|
|
|
=> this.AppendRotationRadians(GeometryUtilities.DegreeToRadian(degrees)); |
|
|
|
/// <param name="scale">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(SizeF scale) |
|
|
|
=> this.PrependScale((Vector2)scale); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a scale matrix from the given uniform scale.
|
|
|
|
/// Prepends a scale matrix from the given vector scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scale">The uniform scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(float scale) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateScale(scale)); |
|
|
|
/// <param name="scales">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(Vector2 scales) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1F))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a scale matrix from the given uniform scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scale">The uniform scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendScale(float scale) |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateScale(scale)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a scale matrix from the given vector scale.
|
|
|
|
/// Appends a scale matrix from the given vector scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scales">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(Vector2 scales) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1f))); |
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendScale(SizeF scales) |
|
|
|
=> this.AppendScale((Vector2)scales); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a scale matrix from the given vector scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scales">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendScale(Vector2 scales) |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1f))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a scale matrix from the given vector scale.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scale">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependScale(SizeF scale) |
|
|
|
=> this.PrependScale((Vector2)scale); |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateScale(new Vector3(scales, 1F))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a scale matrix from the given vector scale.
|
|
|
|
/// Prepends a translation matrix from the given vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="scales">The horizontal and vertical scale.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendScale(SizeF scales) |
|
|
|
=> this.AppendScale((Vector2)scales); |
|
|
|
/// <param name="position">The translation position.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependTranslation(PointF position) |
|
|
|
=> this.PrependTranslation((Vector2)position); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a translation matrix from the given vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="position">The translation position.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependTranslation(Vector2 position) |
|
|
|
=> this.PrependMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); |
|
|
|
|
|
|
|
@ -184,68 +154,72 @@ namespace SixLabors.ImageSharp.Processing |
|
|
|
/// Appends a translation matrix from the given vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="position">The translation position.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendTranslation(Vector2 position) |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a translation matrix from the given vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="position">The translation position.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependTranslation(PointF position) |
|
|
|
=> this.PrependTranslation((Vector2)position); |
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendTranslation(PointF position) |
|
|
|
=> this.AppendTranslation((Vector2)position); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a translation matrix from the given vector.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="position">The translation position.</param>
|
|
|
|
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendTranslation(PointF position) |
|
|
|
=> this.AppendTranslation((Vector2)position); |
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendTranslation(Vector2 position) |
|
|
|
=> this.AppendMatrix(Matrix4x4.CreateTranslation(new Vector3(position, 0))); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prepends a raw matrix.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="matrix">The matrix to prepend.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix) |
|
|
|
{ |
|
|
|
this.matrices.Insert(0, matrix); |
|
|
|
return this; |
|
|
|
} |
|
|
|
public ProjectiveTransformBuilder PrependMatrix(Matrix4x4 matrix) => this.Prepend(_ => matrix); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Appends a raw matrix.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="matrix">The matrix to append.</param>
|
|
|
|
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
|
|
|
|
public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix) |
|
|
|
{ |
|
|
|
this.matrices.Add(matrix); |
|
|
|
return this; |
|
|
|
} |
|
|
|
public ProjectiveTransformBuilder AppendMatrix(Matrix4x4 matrix) => this.Append(_ => matrix); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns the combined matrix for a given source size.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="sourceSize">The source image size.</param>
|
|
|
|
/// <returns>The <see cref="Matrix4x4"/>.</returns>
|
|
|
|
public Matrix4x4 BuildMatrix(Size sourceSize) => this.BuildMatrix(new Rectangle(Point.Empty, sourceSize)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns the combined matrix.
|
|
|
|
/// Returns the combined matrix for a given source rectangle.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="sourceRectangle">The rectangle in the source image.</param>
|
|
|
|
/// <returns>The <see cref="Matrix4x4"/>.</returns>
|
|
|
|
public Matrix4x4 BuildMatrix() |
|
|
|
public Matrix4x4 BuildMatrix(Rectangle sourceRectangle) |
|
|
|
{ |
|
|
|
Matrix4x4 matrix = Matrix4x4.Identity; |
|
|
|
Guard.MustBeGreaterThan(sourceRectangle.Width, 0, nameof(sourceRectangle)); |
|
|
|
Guard.MustBeGreaterThan(sourceRectangle.Height, 0, nameof(sourceRectangle)); |
|
|
|
|
|
|
|
// Translate the origin matrix to cater for source rectangle offsets.
|
|
|
|
if (!this.sourceRectangle.Equals(default)) |
|
|
|
{ |
|
|
|
matrix *= Matrix4x4.CreateTranslation(new Vector3(-this.sourceRectangle.Location, 0)); |
|
|
|
} |
|
|
|
var matrix = Matrix4x4.CreateTranslation(new Vector3(-sourceRectangle.Location, 0)); |
|
|
|
|
|
|
|
Size size = sourceRectangle.Size; |
|
|
|
|
|
|
|
foreach (Matrix4x4 m in this.matrices) |
|
|
|
foreach (Func<Size, Matrix4x4> factory in this.matrixFactories) |
|
|
|
{ |
|
|
|
matrix *= m; |
|
|
|
matrix *= factory(size); |
|
|
|
} |
|
|
|
|
|
|
|
return matrix; |
|
|
|
} |
|
|
|
|
|
|
|
private ProjectiveTransformBuilder Prepend(Func<Size, Matrix4x4> factory) |
|
|
|
{ |
|
|
|
this.matrixFactories.Insert(0, factory); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
private ProjectiveTransformBuilder Append(Func<Size, Matrix4x4> factory) |
|
|
|
{ |
|
|
|
this.matrixFactories.Add(factory); |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
} |