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)] [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 Convolve(Span<Vector4> rowSpan) public Vector4 Convolve(Span<Vector4> rowSpan)
{ {
ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), this.StartIndex); return this.ConvolveCore(rowSpan.Slice(this.StartIndex));
return this.ConvolveCore(ref vecPtr);
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ConvolveCore(ref Vector4 rowStartRef) public Vector4 ConvolveCore(Span<Vector4> offsetedRowSpan)
{ {
ref float horizontalValues = ref Unsafe.AsRef<float>(this.bufferPtr); ref float horizontalValues = ref Unsafe.AsRef<float>(this.bufferPtr);
// Destination color components // Destination color components
@ -70,7 +68,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int i = 0; i < this.Length; i++) for (int i = 0; i < this.Length; i++)
{ {
float weight = Unsafe.Add(ref horizontalValues, 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; 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++) for (int x = 0; x < width; x++)
{ {
Span<Vector4> firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex); Span<Vector4> firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex);
ref Vector4 rowStartReference = ref MemoryMarshal.GetReference(firstPassColumn);
// Destination color components // 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); 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 diameter;
private readonly int windowHeight;
public ResizeWindow( public ResizeWindow(
Configuration configuration, Configuration configuration,
BufferArea<TPixel> source, BufferArea<TPixel> source,
@ -59,15 +61,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.diameter = verticalKernelMap.MaxDiameter; this.diameter = verticalKernelMap.MaxDiameter;
this.windowHeight = Math.Min(this.sourceRectangle.Height, 2 * this.diameter);
this.buffer = configuration.MemoryAllocator.Allocate2D<Vector4>( this.buffer = configuration.MemoryAllocator.Allocate2D<Vector4>(
this.sourceRectangle.Height, this.windowHeight,
destWidth, destWidth,
AllocationOptions.Clean); AllocationOptions.Clean);
this.tempRowBuffer = configuration.MemoryAllocator.Allocate<Vector4>(this.sourceRectangle.Width); this.tempRowBuffer = configuration.MemoryAllocator.Allocate<Vector4>(this.sourceRectangle.Width);
this.Top = 0;
this.Bottom = this.sourceRectangle.Height;
} }
public int Bottom { get; private set; } public int Bottom { get; private set; }
@ -82,21 +82,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<Vector4> GetColumnSpan(int x, int startY) 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() public void Initialize()
{ {
this.Initialize(0, this.sourceRectangle.Height); this.Initialize(0, this.windowHeight);
} }
public void Slide() 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) private void Initialize(int top, int bottom)
{ {
this.Top = top;
this.Bottom = bottom;
Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan(); Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan();
for (int y = top; y < bottom; y++) for (int y = top; y < bottom; y++)
{ {
@ -108,12 +113,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
tempRowSpan, tempRowSpan,
this.conversionModifiers); 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++) for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++)
{ {
ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); 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: // [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] means:
// resizing: (15, 12) -> (10, 6) // resizing: (15, 12) -> (10, 6)
// kernel dimensions: (3, 4) // kernel dimensions: (3, 4)
using (Image<TPixel> image = provider.GetImage()) using (Image<TPixel> image = provider.GetImage())
{ {

Loading…
Cancel
Save