Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions src/ImageSharp/Primitives/Point.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public Point(Size size)
/// Gets a value indicating whether this <see cref="Point"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
public readonly bool IsEmpty => this.Equals(Empty);

/// <summary>
/// Creates a <see cref="PointF"/> with the coordinates of the specified <see cref="Point"/>.
Expand Down Expand Up @@ -239,7 +239,7 @@ public Point(Size size)
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
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;
Expand Down Expand Up @@ -268,17 +268,17 @@ public void Offset(int dx, int dy)
public void Offset(Point point) => this.Offset(point.X, point.Y);

/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
public override readonly int GetHashCode() => HashCode.Combine(this.X, this.Y);

/// <inheritdoc/>
public override string ToString() => $"Point [ X={this.X}, Y={this.Y} ]";
public override readonly string ToString() => $"Point [ X={this.X}, Y={this.Y} ]";

/// <inheritdoc/>
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);

/// <inheritdoc/>
[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));

Expand Down
12 changes: 6 additions & 6 deletions src/ImageSharp/Primitives/PointF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public PointF(SizeF size)
/// Gets a value indicating whether this <see cref="PointF"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
public readonly bool IsEmpty => this.Equals(Empty);

/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
Expand Down Expand Up @@ -251,7 +251,7 @@ public PointF(SizeF size)
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
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;
Expand All @@ -277,15 +277,15 @@ public void Offset(float dx, float dy)
public void Offset(PointF point) => this.Offset(point.X, point.Y);

/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
public override readonly int GetHashCode() => HashCode.Combine(this.X, this.Y);

/// <inheritdoc/>
public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]";
public override readonly string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]";

/// <inheritdoc/>
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);

/// <inheritdoc/>
[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);
}
12 changes: 6 additions & 6 deletions src/ImageSharp/Primitives/SizeF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public SizeF(PointF point)
/// Gets a value indicating whether this <see cref="SizeF"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
public readonly bool IsEmpty => this.Equals(Empty);

/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
Expand Down Expand Up @@ -201,24 +201,24 @@ public static SizeF Transform(SizeF size, Matrix3x2 matrix)
/// </summary>
/// <param name="width">The out value for the width.</param>
/// <param name="height">The out value for the height.</param>
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;
}

/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.Width, this.Height);
public override readonly int GetHashCode() => HashCode.Combine(this.Width, this.Height);

/// <inheritdoc/>
public override string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]";
public override readonly string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]";

/// <inheritdoc/>
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);

/// <inheritdoc/>
[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);

/// <summary>
/// Multiplies <see cref="SizeF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
Expand Down
41 changes: 20 additions & 21 deletions src/ImageSharp/Processing/AffineTransformBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,9 @@ public class AffineTransformBuilder
/// Initializes a new instance of the <see cref="AffineTransformBuilder"/> class.
/// </summary>
public AffineTransformBuilder()
: this(TransformSpace.Pixel)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="AffineTransformBuilder"/> class.
/// </summary>
/// <param name="transformSpace">
/// The <see cref="TransformSpace"/> to use when applying the affine transform.
/// </param>
public AffineTransformBuilder(TransformSpace transformSpace)
=> this.TransformSpace = transformSpace;

/// <summary>
/// Gets the <see cref="TransformSpace"/> to use when applying the affine transform.
/// </summary>
public TransformSpace TransformSpace { get; }

/// <summary>
/// Prepends a rotation matrix using the given rotation angle in degrees
/// and the image center point as rotation center.
Expand All @@ -52,7 +37,7 @@ public AffineTransformBuilder PrependRotationDegrees(float degrees)
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder PrependRotationRadians(float radians)
=> this.Prepend(
size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace));
size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size));

/// <summary>
/// Prepends a rotation matrix using the given rotation in degrees at the given origin.
Expand Down Expand Up @@ -88,7 +73,7 @@ public AffineTransformBuilder AppendRotationDegrees(float degrees)
/// <param name="radians">The amount of rotation, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder AppendRotationRadians(float radians)
=> this.Append(size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size, this.TransformSpace));
=> this.Append(size => TransformUtils.CreateRotationTransformMatrixRadians(radians, size));

/// <summary>
/// Appends a rotation matrix using the given rotation in degrees at the given origin.
Expand Down Expand Up @@ -172,7 +157,7 @@ public AffineTransformBuilder PrependSkewDegrees(float degreesX, float degreesY)
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
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));

/// <summary>
/// Prepends a skew matrix using the given angles in degrees at the given origin.
Expand Down Expand Up @@ -210,7 +195,7 @@ public AffineTransformBuilder AppendSkewDegrees(float degreesX, float degreesY)
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
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));

/// <summary>
/// Appends a skew matrix using the given angles in degrees at the given origin.
Expand Down Expand Up @@ -344,12 +329,26 @@ public Matrix3x2 BuildMatrix(Rectangle sourceRectangle)
/// for linear transforms.
/// </exception>
/// <returns>The <see cref="Size"/>.</returns>
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);
}

/// <summary>
/// Returns the size of a rectangle large enough to contain the transformed source rectangle.
/// </summary>
/// <param name="sourceRectangle">The rectangle in the source image.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <exception cref="DegenerateTransformException">
/// The resultant matrix is degenerate containing one or more values equivalent
/// to <see cref="float.NaN"/> or a zero determinant and therefore cannot be used
/// for linear transforms.
/// </exception>
/// <returns>The <see cref="Size"/>.</returns>
internal static SizeF GetTransformedSize(Rectangle sourceRectangle, Matrix3x2 matrix)
=> TransformUtils.GetRawTransformedSize(matrix, sourceRectangle.Size);

private static void CheckDegenerate(Matrix3x2 matrix)
{
if (TransformUtils.IsDegenerate(matrix))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
namespace SixLabors.ImageSharp.Processing;

/// <summary>
/// Defines extensions that allow the application of composable transform operations on an <see cref="Image"/>
/// using Mutate/Clone.
/// Defines extensions that allow the application of composable transform operations
/// on an <see cref="IImageProcessingContext"/> using Mutate/Clone.
/// </summary>
public static class TransformExtensions
{
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ public void ApplyTransform<TResampler>(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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ public void ApplyTransform<TResampler>(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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public RotateProcessor(float degrees, Size sourceSize)
/// <param name="sourceSize">The source image size</param>
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))
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public SkewProcessor(float degreesX, float degreesY, Size sourceSize)
/// <param name="sourceSize">The source image size</param>
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)
{
Expand All @@ -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))
{
}

Expand Down
Loading
Loading