Browse Source

Refactored AffineTransformProcessor<TPixel>

pull/1574/head
Sergio Pedri 6 years ago
parent
commit
a71bcd2a21
  1. 83
      src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs

83
src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs

@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (sampler is NearestNeighborResampler) if (sampler is NearestNeighborResampler)
{ {
var nnOperation = new NNAffineOperation(source, destination, matrix); var nnOperation = new NNAffineOperation(source, destination, matrix);
ParallelRowIterator.IterateRowIntervals( ParallelRowIterator.IterateRows(
configuration, configuration,
destination.Bounds(), destination.Bounds(),
in nnOperation); in nnOperation);
@ -105,13 +105,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
radialExtents, radialExtents,
maxSourceExtents); maxSourceExtents);
ParallelRowIterator.IterateRowIntervals<AffineOperation<TResampler>, Vector4>( ParallelRowIterator.IterateRows<AffineOperation<TResampler>, Vector4>(
configuration, configuration,
destination.Bounds(), destination.Bounds(),
in operation); in operation);
} }
private readonly struct NNAffineOperation : IRowIntervalOperation private readonly struct NNAffineOperation : IRowOperation
{ {
private readonly ImageFrame<TPixel> source; private readonly ImageFrame<TPixel> source;
private readonly ImageFrame<TPixel> destination; private readonly ImageFrame<TPixel> destination;
@ -133,28 +133,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
} }
[MethodImpl(InliningOptions.ShortMethod)] [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); destRow[x] = this.source[px, py];
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];
}
} }
} }
} }
} }
private readonly struct AffineOperation<TResampler> : IRowIntervalOperation<Vector4> private readonly struct AffineOperation<TResampler> : IRowOperation<Vector4>
where TResampler : struct, IResampler where TResampler : struct, IResampler
{ {
private readonly Configuration configuration; private readonly Configuration configuration;
@ -193,41 +190,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
} }
[MethodImpl(InliningOptions.ShortMethod)] [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; 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)); PixelOperations<TPixel>.Instance.ToVector4(
ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y)); this.configuration,
this.destination.GetPixelRowSpan(y),
span);
for (int x = 0; x < this.maxX; x++) ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y));
{ ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y));
// 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);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive( for (int x = 0; x < this.maxX; x++)
this.configuration, {
// 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, 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));
} }
} }
} }

Loading…
Cancel
Save