|
|
|
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms |
|
|
|
if (sampler is NearestNeighborResampler) |
|
|
|
{ |
|
|
|
var nnOperation = new NNAffineOperation(source, destination, matrix); |
|
|
|
ParallelRowIterator.IterateRowIntervals( |
|
|
|
ParallelRowIterator.IterateRows( |
|
|
|
configuration, |
|
|
|
destination.Bounds(), |
|
|
|
in nnOperation); |
|
|
|
@ -105,13 +105,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms |
|
|
|
radialExtents, |
|
|
|
maxSourceExtents); |
|
|
|
|
|
|
|
ParallelRowIterator.IterateRowIntervals<AffineOperation<TResampler>, Vector4>( |
|
|
|
ParallelRowIterator.IterateRows<AffineOperation<TResampler>, Vector4>( |
|
|
|
configuration, |
|
|
|
destination.Bounds(), |
|
|
|
in operation); |
|
|
|
} |
|
|
|
|
|
|
|
private readonly struct NNAffineOperation : IRowIntervalOperation |
|
|
|
private readonly struct NNAffineOperation : IRowOperation |
|
|
|
{ |
|
|
|
private readonly ImageFrame<TPixel> source; |
|
|
|
private readonly ImageFrame<TPixel> destination; |
|
|
|
@ -133,28 +133,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms |
|
|
|
} |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(in RowInterval rows) |
|
|
|
public void Invoke(int y) |
|
|
|
{ |
|
|
|
for (int y = rows.Min; y < rows.Max; y++) |
|
|
|
Span<TPixel> destRow = this.destination.GetPixelRowSpan(y); |
|
|
|
|
|
|
|
for (int x = 0; x < this.maxX; x++) |
|
|
|
{ |
|
|
|
Span<TPixel> destRow = this.destination.GetPixelRowSpan(y); |
|
|
|
var point = Vector2.Transform(new Vector2(x, y), this.matrix); |
|
|
|
int px = (int)MathF.Round(point.X); |
|
|
|
int py = (int)MathF.Round(point.Y); |
|
|
|
|
|
|
|
for (int x = 0; x < this.maxX; x++) |
|
|
|
if (this.bounds.Contains(px, py)) |
|
|
|
{ |
|
|
|
var 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[px, py]; |
|
|
|
} |
|
|
|
destRow[x] = this.source[px, py]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private readonly struct AffineOperation<TResampler> : IRowIntervalOperation<Vector4> |
|
|
|
private readonly struct AffineOperation<TResampler> : IRowOperation<Vector4> |
|
|
|
where TResampler : struct, IResampler |
|
|
|
{ |
|
|
|
private readonly Configuration configuration; |
|
|
|
@ -193,41 +190,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms |
|
|
|
} |
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
|
public void Invoke(in RowInterval rows, Span<Vector4> span) |
|
|
|
public void Invoke(int y, Span<Vector4> span) |
|
|
|
{ |
|
|
|
Buffer2D<TPixel> sourceBuffer = this.source.PixelBuffer; |
|
|
|
for (int y = rows.Min; y < rows.Max; y++) |
|
|
|
{ |
|
|
|
PixelOperations<TPixel>.Instance.ToVector4( |
|
|
|
this.configuration, |
|
|
|
this.destination.GetPixelRowSpan(y), |
|
|
|
span); |
|
|
|
|
|
|
|
ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y)); |
|
|
|
ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y)); |
|
|
|
PixelOperations<TPixel>.Instance.ToVector4( |
|
|
|
this.configuration, |
|
|
|
this.destination.GetPixelRowSpan(y), |
|
|
|
span); |
|
|
|
|
|
|
|
for (int x = 0; x < this.maxX; x++) |
|
|
|
{ |
|
|
|
// Use the single precision position to calculate correct bounding pixels
|
|
|
|
// otherwise we get rogue pixels outside of the bounds.
|
|
|
|
var point = Vector2.Transform(new Vector2(x, y), this.matrix); |
|
|
|
LinearTransformUtilities.Convolve( |
|
|
|
in this.sampler, |
|
|
|
point, |
|
|
|
sourceBuffer, |
|
|
|
span, |
|
|
|
x, |
|
|
|
ref yKernelSpanRef, |
|
|
|
ref xKernelSpanRef, |
|
|
|
this.radialExtents, |
|
|
|
this.maxSourceExtents); |
|
|
|
} |
|
|
|
ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y)); |
|
|
|
ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y)); |
|
|
|
|
|
|
|
PixelOperations<TPixel>.Instance.FromVector4Destructive( |
|
|
|
this.configuration, |
|
|
|
for (int x = 0; x < this.maxX; x++) |
|
|
|
{ |
|
|
|
// Use the single precision position to calculate correct bounding pixels
|
|
|
|
// otherwise we get rogue pixels outside of the bounds.
|
|
|
|
var point = Vector2.Transform(new Vector2(x, y), this.matrix); |
|
|
|
LinearTransformUtilities.Convolve( |
|
|
|
in this.sampler, |
|
|
|
point, |
|
|
|
sourceBuffer, |
|
|
|
span, |
|
|
|
this.destination.GetPixelRowSpan(y)); |
|
|
|
x, |
|
|
|
ref yKernelSpanRef, |
|
|
|
ref xKernelSpanRef, |
|
|
|
this.radialExtents, |
|
|
|
this.maxSourceExtents); |
|
|
|
} |
|
|
|
|
|
|
|
PixelOperations<TPixel>.Instance.FromVector4Destructive( |
|
|
|
this.configuration, |
|
|
|
span, |
|
|
|
this.destination.GetPixelRowSpan(y)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|