diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs
index 4d70fba84..87f28045c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
+using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@@ -91,5 +92,48 @@ namespace SixLabors.ImageSharp.Processing.Processors
var translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F);
return (translationToTargetCenter * matrix) * translateToSourceCenter;
}
+
+ ///
+ /// Computes the weighted sum at the given XY position
+ ///
+ /// The source image
+ /// The maximum x value
+ /// The maximum y value
+ /// The horizontal weights
+ /// The vertical weights
+ /// The transformed position
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected Vector4 ComputeWeightedSumAtPosition(ImageFrame source, int maxX, int maxY, ref WeightsWindow windowX, ref WeightsWindow windowY, ref Point point)
+ {
+ ref float horizontalValues = ref windowX.GetStartReference();
+ ref float verticalValues = ref windowY.GetStartReference();
+ int xLeft = windowX.Left;
+ int yLeft = windowY.Left;
+ int xLength = windowX.Length;
+ int yLength = windowY.Length;
+ Vector4 result = Vector4.Zero;
+
+ // TODO: Fix this.
+ // Currently the output image is the separable values duplicated with half the transform applied
+ // and not the combined values as it should be. I must be sampling the wrong values.
+ for (int i = 0; i < xLength; i++)
+ {
+ int offsetX = xLeft + i + point.X;
+ offsetX = offsetX.Clamp(0, maxX);
+ float weight = Unsafe.Add(ref horizontalValues, i);
+ result += source[offsetX, point.Y].ToVector4() * weight;
+ }
+
+ for (int i = 0; i < yLength; i++)
+ {
+ int offsetY = yLeft + i + point.Y;
+ offsetY = offsetY.Clamp(0, maxY);
+ float weight = Unsafe.Add(ref verticalValues, i);
+ result += source[point.X, offsetY].ToVector4() * weight;
+ }
+
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
index f47d48359..50b28a831 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
@@ -86,7 +86,33 @@ namespace SixLabors.ImageSharp.Processing.Processors
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.CreateProcessingMatrix());
Rectangle sourceBounds = source.Bounds();
- // TODO: Use our new weights functionality to resample on transform
+ if (this.Sampler is NearestNeighborResampler)
+ {
+ Parallel.For(
+ 0,
+ height,
+ configuration.ParallelOptions,
+ y =>
+ {
+ Span destRow = destination.GetPixelRowSpan(y);
+
+ for (int x = 0; x < width; x++)
+ {
+ var transformedPoint = Point.Rotate(new Point(x, y), matrix);
+
+ if (sourceBounds.Contains(transformedPoint.X, transformedPoint.Y))
+ {
+ destRow[x] = source[transformedPoint.X, transformedPoint.Y];
+ }
+ }
+ });
+
+ return;
+ }
+
+ int maxX = source.Height - 1;
+ int maxY = source.Width - 1;
+
Parallel.For(
0,
height,
@@ -94,14 +120,16 @@ namespace SixLabors.ImageSharp.Processing.Processors
y =>
{
Span destRow = destination.GetPixelRowSpan(y);
-
for (int x = 0; x < width; x++)
{
var transformedPoint = Point.Rotate(new Point(x, y), matrix);
-
if (sourceBounds.Contains(transformedPoint.X, transformedPoint.Y))
{
- destRow[x] = source[transformedPoint.X, transformedPoint.Y];
+ WeightsWindow windowX = this.HorizontalWeights.Weights[transformedPoint.X];
+ WeightsWindow windowY = this.VerticalWeights.Weights[transformedPoint.Y];
+ Vector4 dXY = this.ComputeWeightedSumAtPosition(source, maxX, maxY, ref windowX, ref windowY, ref transformedPoint);
+ ref TPixel dest = ref destRow[x];
+ dest.PackFromVector4(dXY);
}
}
});
diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs
index ba84eab9e..233055995 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs
@@ -58,7 +58,33 @@ namespace SixLabors.ImageSharp.Processing.Processors
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.CreateProcessingMatrix());
Rectangle sourceBounds = source.Bounds();
- // TODO: Use our new weights functionality to resample on transform
+ if (this.Sampler is NearestNeighborResampler)
+ {
+ Parallel.For(
+ 0,
+ height,
+ configuration.ParallelOptions,
+ y =>
+ {
+ Span destRow = destination.GetPixelRowSpan(y);
+
+ for (int x = 0; x < width; x++)
+ {
+ var transformedPoint = Point.Skew(new Point(x, y), matrix);
+
+ if (sourceBounds.Contains(transformedPoint.X, transformedPoint.Y))
+ {
+ destRow[x] = source[transformedPoint.X, transformedPoint.Y];
+ }
+ }
+ });
+
+ return;
+ }
+
+ int maxX = source.Height - 1;
+ int maxY = source.Width - 1;
+
Parallel.For(
0,
height,
@@ -66,14 +92,17 @@ namespace SixLabors.ImageSharp.Processing.Processors
y =>
{
Span destRow = destination.GetPixelRowSpan(y);
-
for (int x = 0; x < width; x++)
{
var transformedPoint = Point.Skew(new Point(x, y), matrix);
-
if (sourceBounds.Contains(transformedPoint.X, transformedPoint.Y))
{
- destRow[x] = source[transformedPoint.X, transformedPoint.Y];
+ WeightsWindow windowX = this.HorizontalWeights.Weights[transformedPoint.X];
+ WeightsWindow windowY = this.VerticalWeights.Weights[transformedPoint.Y];
+
+ Vector4 dXY = this.ComputeWeightedSumAtPosition(source, maxX, maxY, ref windowX, ref windowY, ref transformedPoint);
+ ref TPixel dest = ref destRow[x];
+ dest.PackFromVector4(dXY);
}
}
});