Browse Source

ResizeWindow refactor 4

pull/888/head
Anton Firszov 7 years ago
parent
commit
20ddd11e5f
  1. 29
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
  2. 17
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
  3. 33
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs
  4. 2
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs
  5. 4
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs

29
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs

@ -19,27 +19,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// Initializes a new instance of the <see cref="ResizeKernel"/> struct.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
internal ResizeKernel(int left, float* bufferPtr, int length)
internal ResizeKernel(int startIndex, float* bufferPtr, int length)
{
this.Left = left;
this.StartIndex = startIndex;
this.bufferPtr = bufferPtr;
this.Length = length;
}
/// <summary>
/// Gets the left index for the destination row
/// Gets the start index for the destination row.
/// </summary>
public int Left { get; }
public int StartIndex { get; }
/// <summary>
/// Gets the the length of the kernel
/// Gets the the length of the kernel.
/// </summary>
public int Length { get; }
/// <summary>
/// Gets the span representing the portion of the <see cref="ResizeKernelMap"/> that this window covers
/// Gets the span representing the portion of the <see cref="ResizeKernelMap"/> that this window covers.
/// </summary>
/// <value>The <see cref="Span{T}"/>
/// <value>The <see cref="Span{T}"/>.
/// </value>
public Span<float> Values
{
@ -55,17 +55,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 Convolve(Span<Vector4> rowSpan)
{
ref float horizontalValues = ref Unsafe.AsRef<float>(this.bufferPtr);
int left = this.Left;
ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left);
ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), this.StartIndex);
return this.ConvolveCore(ref vecPtr);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ConvolveCore(ref Vector4 rowStartRef)
{
ref float horizontalValues = ref Unsafe.AsRef<float>(this.bufferPtr);
// Destination color components
Vector4 result = Vector4.Zero;
for (int i = 0; i < this.Length; i++)
{
float weight = Unsafe.Add(ref horizontalValues, i);
Vector4 v = Unsafe.Add(ref vecPtr, i);
Vector4 v = Unsafe.Add(ref rowStartRef, i);
result += v * weight;
}
@ -73,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
/// <summary>
/// Copy the contents of <see cref="ResizeKernel"/> altering <see cref="Left"/>
/// Copy the contents of <see cref="ResizeKernel"/> altering <see cref="StartIndex"/>
/// to the value <paramref name="left"/>.
/// </summary>
internal ResizeKernel AlterLeftValue(int left)

17
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs

@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int startY = this.TargetRectangle.Y;
int startX = this.TargetRectangle.X;
var workingRect = Rectangle.Intersect(
var destWorkingRect = Rectangle.Intersect(
this.TargetRectangle,
new Rectangle(0, 0, width, height));
@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height;
ParallelHelper.IterateRows(
workingRect,
destWorkingRect,
configuration,
rows =>
{
@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY));
Span<TPixel> targetRow = destination.GetPixelRowSpan(y);
for (int x = workingRect.Left; x < workingRect.Right; x++)
for (int x = destWorkingRect.Left; x < destWorkingRect.Right; x++)
{
// X coordinates of source points
targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)];
@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.horizontalKernelMap,
this.verticalKernelMap,
width,
workingRect,
destWorkingRect,
startX))
using (IMemoryOwner<Vector4> tempBuffer = source.MemoryAllocator.Allocate<Vector4>(width))
{
@ -257,12 +257,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Now process the rows.
Span<Vector4> tempColSpan = tempBuffer.GetSpan();
for (int y = workingRect.Top; y < workingRect.Bottom; y++)
for (int y = destWorkingRect.Top; y < destWorkingRect.Bottom; y++)
{
// Ensure offsets are normalized for cropping and padding.
ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY);
if (kernel.Left + kernel.Length > resizeWindow.Bottom)
if (kernel.StartIndex + kernel.Length > resizeWindow.Bottom)
{
resizeWindow.Slide();
}
@ -271,10 +271,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int x = 0; x < width; x++)
{
Span<Vector4> firstPassColumn = resizeWindow.GetColumnSpan(x);
Span<Vector4> firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex);
ref Vector4 rowStartReference = ref MemoryMarshal.GetReference(firstPassColumn);
// Destination color components
Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn);
Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref rowStartReference);
}
Span<TPixel> targetRowSpan = destination.GetPixelRowSpan(y);

33
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs

@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ResizeKernelMap verticalKernelMap;
private readonly Rectangle workingRectangle;
private readonly Rectangle destWorkingRect;
private readonly int diameter;
@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ResizeKernelMap horizontalKernelMap,
ResizeKernelMap verticalKernelMap,
int destWidth,
Rectangle workingRectangle,
Rectangle destWorkingRect,
int startX)
{
this.configuration = configuration;
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.conversionModifiers = conversionModifiers;
this.horizontalKernelMap = horizontalKernelMap;
this.verticalKernelMap = verticalKernelMap;
this.workingRectangle = workingRectangle;
this.destWorkingRect = destWorkingRect;
this.startX = startX;
this.diameter = verticalKernelMap.MaxDiameter;
@ -65,9 +65,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
AllocationOptions.Clean);
this.tempRowBuffer = configuration.MemoryAllocator.Allocate<Vector4>(this.sourceRectangle.Width);
this.Top = this.sourceRectangle.Top;
this.Top = 0;
this.Bottom = this.sourceRectangle.Bottom;
this.Bottom = this.sourceRectangle.Height;
}
public int Bottom { get; private set; }
@ -80,15 +80,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<Vector4> GetColumnSpan(int x)
public Span<Vector4> GetColumnSpan(int x, int startY)
{
return this.buffer.GetRowSpan(x);
return this.buffer.GetRowSpan(x).Slice(startY);
}
public void Initialize()
{
this.Initialize(0, this.sourceRectangle.Height);
}
public void Slide()
{
throw new InvalidOperationException("Shouldn't happen yet!");
}
private void Initialize(int top, int bottom)
{
Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan();
for (int y = 0; y < this.sourceRectangle.Height; y++)
for (int y = top; y < bottom; y++)
{
Span<TPixel> sourceRow = this.source.GetRowSpan(y);
@ -100,17 +110,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ref Vector4 firstPassBaseRef = ref this.buffer.Span[y];
for (int x = this.workingRectangle.Left; x < this.workingRectangle.Right; x++)
for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++)
{
ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX);
Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan);
}
}
}
public void Slide()
{
throw new InvalidOperationException("Shouldn't happen yet!");
}
}
}

2
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs

@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
public static implicit operator ReferenceKernel(ResizeKernel orig)
{
return new ReferenceKernel(orig.Left, orig.Values.ToArray());
return new ReferenceKernel(orig.StartIndex, orig.Values.ToArray());
}
}
}

4
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs

@ -151,8 +151,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
referenceKernel.Length == kernel.Length,
$"referenceKernel.Length != kernel.Length: {referenceKernel.Length} != {kernel.Length}");
Assert.True(
referenceKernel.Left == kernel.Left,
$"referenceKernel.Left != kernel.Left: {referenceKernel.Left} != {kernel.Left}");
referenceKernel.Left == kernel.StartIndex,
$"referenceKernel.Left != kernel.Left: {referenceKernel.Left} != {kernel.StartIndex}");
float[] expectedValues = referenceKernel.Values;
Span<float> actualValues = kernel.Values;

Loading…
Cancel
Save