Browse Source

basic sliding window implementation (semi-stable state)

pull/888/head
Anton Firszov 7 years ago
parent
commit
86cc83d7ea
  1. 9
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs
  2. 3
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
  3. 27
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs
  4. 1
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs

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

@ -55,13 +55,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 Convolve(Span<Vector4> rowSpan)
{
ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), this.StartIndex);
return this.ConvolveCore(ref vecPtr);
return this.ConvolveCore(rowSpan.Slice(this.StartIndex));
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ConvolveCore(ref Vector4 rowStartRef)
public Vector4 ConvolveCore(Span<Vector4> offsetedRowSpan)
{
ref float horizontalValues = ref Unsafe.AsRef<float>(this.bufferPtr);
// Destination color components
@ -70,7 +68,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int i = 0; i < this.Length; i++)
{
float weight = Unsafe.Add(ref horizontalValues, i);
Vector4 v = Unsafe.Add(ref rowStartRef, i);
//Vector4 v = Unsafe.Add(ref rowStartRef, i);
Vector4 v = offsetedRowSpan[i];
result += v * weight;
}

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

@ -272,10 +272,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int x = 0; x < width; 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.ConvolveCore(ref rowStartReference);
Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn);
}
Span<TPixel> targetRowSpan = destination.GetPixelRowSpan(y);

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

@ -38,6 +38,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly int diameter;
private readonly int windowHeight;
public ResizeWindow(
Configuration configuration,
BufferArea<TPixel> source,
@ -59,15 +61,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.diameter = verticalKernelMap.MaxDiameter;
this.windowHeight = Math.Min(this.sourceRectangle.Height, 2 * this.diameter);
this.buffer = configuration.MemoryAllocator.Allocate2D<Vector4>(
this.sourceRectangle.Height,
this.windowHeight,
destWidth,
AllocationOptions.Clean);
this.tempRowBuffer = configuration.MemoryAllocator.Allocate<Vector4>(this.sourceRectangle.Width);
this.Top = 0;
this.Bottom = this.sourceRectangle.Height;
}
public int Bottom { get; private set; }
@ -82,21 +82,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<Vector4> GetColumnSpan(int x, int startY)
{
return this.buffer.GetRowSpan(x).Slice(startY);
return this.buffer.GetRowSpan(x).Slice(startY - this.Top);
}
public void Initialize()
{
this.Initialize(0, this.sourceRectangle.Height);
this.Initialize(0, this.windowHeight);
}
public void Slide()
{
throw new InvalidOperationException("Shouldn't happen yet!");
int top = this.Top + this.diameter;
int bottom = Math.Min(this.Bottom + this.diameter, this.sourceRectangle.Height);
this.Initialize(top, bottom);
}
private void Initialize(int top, int bottom)
{
this.Top = top;
this.Bottom = bottom;
Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan();
for (int y = top; y < bottom; y++)
{
@ -108,12 +113,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
tempRowSpan,
this.conversionModifiers);
ref Vector4 firstPassBaseRef = ref this.buffer.Span[y];
//ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top];
Span<Vector4> firstPassSpan = this.buffer.Span.Slice(y - top);
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);
firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan);
//Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan);
}
}
}

1
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs

@ -102,6 +102,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
// [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] means:
// resizing: (15, 12) -> (10, 6)
// kernel dimensions: (3, 4)
using (Image<TPixel> image = provider.GetImage())
{

Loading…
Cancel
Save