Skip to content

Commit

Permalink
Refactor and fix for transform space
Browse files Browse the repository at this point in the history
  • Loading branch information
JimBobSquarePants committed Oct 21, 2024
1 parent c51d84d commit 3d86c58
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 172 deletions.
79 changes: 0 additions & 79 deletions src/ImageSharp/Common/Helpers/QuadDistortionHelper.cs

This file was deleted.

19 changes: 5 additions & 14 deletions src/ImageSharp/Processing/AffineTransformBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing;
/// </summary>
public class AffineTransformBuilder
{
private readonly List<Func<Size, Matrix3x2>> transformMatrixFactories = new();
private readonly List<Func<Size, Matrix3x2>> transformMatrixFactories = [];

/// <summary>
/// Initializes a new instance of the <see cref="AffineTransformBuilder"/> class.
Expand Down Expand Up @@ -301,7 +301,8 @@ public AffineTransformBuilder AppendMatrix(Matrix3x2 matrix)
/// </summary>
/// <param name="sourceSize">The source image size.</param>
/// <returns>The <see cref="Matrix3x2"/>.</returns>
public Matrix3x2 BuildMatrix(Size sourceSize) => this.BuildMatrix(new Rectangle(Point.Empty, sourceSize));
public Matrix3x2 BuildMatrix(Size sourceSize)
=> this.BuildMatrix(new Rectangle(Point.Empty, sourceSize));

/// <summary>
/// Returns the combined transform matrix for a given source rectangle.
Expand Down Expand Up @@ -345,18 +346,8 @@ public Matrix3x2 BuildMatrix(Rectangle sourceRectangle)
/// <returns>The <see cref="Size"/>.</returns>
public Size GetTransformedSize(Rectangle sourceRectangle)
{
Size size = sourceRectangle.Size;

// Translate the origin matrix to cater for source rectangle offsets.
Matrix3x2 matrix = Matrix3x2.CreateTranslation(-sourceRectangle.Location);

foreach (Func<Size, Matrix3x2> factory in this.transformMatrixFactories)
{
matrix *= factory(size);
CheckDegenerate(matrix);
}

return TransformUtils.GetTransformedSize(matrix, size, this.TransformSpace);
Matrix3x2 matrix = this.BuildMatrix(sourceRectangle);
return TransformUtils.GetTransformedSize(matrix, sourceRectangle.Size, this.TransformSpace);
}

private static void CheckDegenerate(Matrix3x2 matrix)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
if (matrix.Equals(Matrix3x2.Identity))
{
// The clone will be blank here copy all the pixel data over
var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
Rectangle interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
Buffer2DRegion<TPixel> sourceBuffer = source.PixelBuffer.GetRegion(interest);
Buffer2DRegion<TPixel> destbuffer = destination.PixelBuffer.GetRegion(interest);
Buffer2DRegion<TPixel> destinationBuffer = destination.PixelBuffer.GetRegion(interest);
for (int y = 0; y < sourceBuffer.Height; y++)
{
sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y));
sourceBuffer.DangerousGetRowSpan(y).CopyTo(destinationBuffer.DangerousGetRowSpan(y));
}

return;
Expand All @@ -77,7 +77,7 @@ public void ApplyTransform<TResampler>(in TResampler sampler)

if (sampler is NearestNeighborResampler)
{
var nnOperation = new NNAffineOperation(
NNAffineOperation nnOperation = new(
source.PixelBuffer,
Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
destination.PixelBuffer,
Expand All @@ -91,7 +91,7 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
return;
}

var operation = new AffineOperation<TResampler>(
AffineOperation<TResampler> operation = new(
configuration,
source.PixelBuffer,
Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
Expand Down Expand Up @@ -128,17 +128,17 @@ public NNAffineOperation(
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y)
{
Span<TPixel> destRow = this.destination.DangerousGetRowSpan(y);
Span<TPixel> destinationRowSpan = this.destination.DangerousGetRowSpan(y);

for (int x = 0; x < destRow.Length; x++)
for (int x = 0; x < destinationRowSpan.Length; x++)
{
var point = Vector2.Transform(new Vector2(x, y), this.matrix);
Vector2 point = Vector2.Transform(new Vector2(x, y), this.matrix);
int px = (int)MathF.Round(point.X);
int py = (int)MathF.Round(point.Y);

if (this.bounds.Contains(px, py))
{
destRow[x] = this.source.GetElementUnsafe(px, py);
destinationRowSpan[x] = this.source.GetElementUnsafe(px, py);
}
}
}
Expand Down Expand Up @@ -195,16 +195,16 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)

for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> rowSpan = this.destination.DangerousGetRowSpan(y);
Span<TPixel> destinationRowSpan = this.destination.DangerousGetRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(
this.configuration,
rowSpan,
destinationRowSpan,
span,
PixelConversionModifiers.Scale);

for (int x = 0; x < span.Length; x++)
{
var point = Vector2.Transform(new Vector2(x, y), matrix);
Vector2 point = Vector2.Transform(new Vector2(x, y), matrix);
float pY = point.Y;
float pX = point.X;

Expand All @@ -221,13 +221,14 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)
Vector4 sum = Vector4.Zero;
for (int yK = top; yK <= bottom; yK++)
{
Span<TPixel> sourceRowSpan = this.source.DangerousGetRowSpan(yK);
float yWeight = sampler.GetValue(yK - pY);

for (int xK = left; xK <= right; xK++)
{
float xWeight = sampler.GetValue(xK - pX);

Vector4 current = this.source.GetElementUnsafe(xK, yK).ToScaledVector4();
Vector4 current = sourceRowSpan[xK].ToScaledVector4();
Numerics.Premultiply(ref current);
sum += current * xWeight * yWeight;
}
Expand All @@ -240,7 +241,7 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)
PixelOperations<TPixel>.Instance.FromVector4Destructive(
this.configuration,
span,
rowSpan,
destinationRowSpan,
PixelConversionModifiers.Scale);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Common.Helpers;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms.Linear;

/// <summary>
/// Represents a solver for systems of linear equations using the Gaussian Elimination method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
if (matrix.Equals(Matrix4x4.Identity))
{
// The clone will be blank here copy all the pixel data over
var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
Rectangle interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds());
Buffer2DRegion<TPixel> sourceBuffer = source.PixelBuffer.GetRegion(interest);
Buffer2DRegion<TPixel> destbuffer = destination.PixelBuffer.GetRegion(interest);
Buffer2DRegion<TPixel> destinationBuffer = destination.PixelBuffer.GetRegion(interest);
for (int y = 0; y < sourceBuffer.Height; y++)
{
sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y));
sourceBuffer.DangerousGetRowSpan(y).CopyTo(destinationBuffer.DangerousGetRowSpan(y));
}

return;
Expand All @@ -77,7 +77,7 @@ public void ApplyTransform<TResampler>(in TResampler sampler)

if (sampler is NearestNeighborResampler)
{
var nnOperation = new NNProjectiveOperation(
NNProjectiveOperation nnOperation = new(
source.PixelBuffer,
Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
destination.PixelBuffer,
Expand All @@ -91,7 +91,7 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
return;
}

var operation = new ProjectiveOperation<TResampler>(
ProjectiveOperation<TResampler> operation = new(
configuration,
source.PixelBuffer,
Rectangle.Intersect(this.SourceRectangle, source.Bounds()),
Expand Down Expand Up @@ -128,17 +128,17 @@ public NNProjectiveOperation(
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y)
{
Span<TPixel> destRow = this.destination.DangerousGetRowSpan(y);
Span<TPixel> destinationRowSpan = this.destination.DangerousGetRowSpan(y);

for (int x = 0; x < destRow.Length; x++)
for (int x = 0; x < destinationRowSpan.Length; x++)
{
Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix);
int px = (int)MathF.Round(point.X);
int py = (int)MathF.Round(point.Y);

if (this.bounds.Contains(px, py))
{
destRow[x] = this.source.GetElementUnsafe(px, py);
destinationRowSpan[x] = this.source.GetElementUnsafe(px, py);
}
}
}
Expand Down Expand Up @@ -195,10 +195,10 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)

for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> rowSpan = this.destination.DangerousGetRowSpan(y);
Span<TPixel> destinationRowSpan = this.destination.DangerousGetRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(
this.configuration,
rowSpan,
destinationRowSpan,
span,
PixelConversionModifiers.Scale);

Expand All @@ -221,13 +221,14 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)
Vector4 sum = Vector4.Zero;
for (int yK = top; yK <= bottom; yK++)
{
Span<TPixel> sourceRowSpan = this.source.DangerousGetRowSpan(yK);
float yWeight = sampler.GetValue(yK - pY);

for (int xK = left; xK <= right; xK++)
{
float xWeight = sampler.GetValue(xK - pX);

Vector4 current = this.source.GetElementUnsafe(xK, yK).ToScaledVector4();
Vector4 current = sourceRowSpan[xK].ToScaledVector4();
Numerics.Premultiply(ref current);
sum += current * xWeight * yWeight;
}
Expand All @@ -240,7 +241,7 @@ public void Invoke(in RowInterval rows, Span<Vector4> span)
PixelOperations<TPixel>.Instance.FromVector4Destructive(
this.configuration,
span,
rowSpan,
destinationRowSpan,
PixelConversionModifiers.Scale);
}
}
Expand Down
Loading

0 comments on commit 3d86c58

Please sign in to comment.