Browse Source

optimized sliding works!

af/merge-core
Anton Firszov 7 years ago
parent
commit
c8bd3ce9f7
  1. 28
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  2. 17
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs
  3. 23
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

28
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -3,7 +3,9 @@
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.Primitives;
@ -27,8 +29,8 @@ namespace SixLabors.ImageSharp.Memory
{
DebugGuard.NotNull(buffer, nameof(buffer));
DebugGuard.MustBeGreaterThanOrEqualTo(sourceIndex, 0, nameof(sourceIndex));
DebugGuard.MustBeGreaterThanOrEqualTo(destIndex, sourceIndex + columnCount, nameof(destIndex));
DebugGuard.MustBeLessThanOrEqualTo(destIndex, buffer.Width - columnCount, nameof(destIndex));
DebugGuard.MustBeGreaterThanOrEqualTo(destIndex, 0, nameof(sourceIndex));
CheckColumnRegionsDoNotOverlap(buffer, sourceIndex, destIndex, columnCount);
int elementSize = Unsafe.SizeOf<T>();
int width = buffer.Width * elementSize;
@ -36,9 +38,11 @@ namespace SixLabors.ImageSharp.Memory
int dOffset = destIndex * elementSize;
long count = columnCount * elementSize;
using (MemoryHandle handle = buffer.Memory.Pin())
Span<byte> span = MemoryMarshal.AsBytes(buffer.Memory.Span);
fixed (byte* ptr = span)
{
byte* basePtr = (byte*)handle.Pointer;
byte* basePtr = (byte*)ptr;
for (int y = 0; y < buffer.Height; y++)
{
byte* sPtr = basePtr + sOffset;
@ -164,5 +168,21 @@ namespace SixLabors.ImageSharp.Memory
{
return buffer.MemorySource.GetSpan();
}
[Conditional("DEBUG")]
private static void CheckColumnRegionsDoNotOverlap<T>(
Buffer2D<T> buffer,
int sourceIndex,
int destIndex,
int columnCount)
where T : struct
{
int minIndex = Math.Min(sourceIndex, destIndex);
int maxIndex = Math.Max(sourceIndex, destIndex);
if (maxIndex < minIndex + columnCount || maxIndex > buffer.Width - columnCount)
{
throw new InvalidOperationException("Column regions should not overlap!");
}
}
}
}

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

@ -148,14 +148,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int minY = this.currentWindow.Max - this.windowBandHeight;
int maxY = Math.Min(minY + this.workerHeight, this.sourceRectangle.Height);
// Copy previous bottom band to the new top:
// (rows <--> columns, because the buffer is transposed)
this.transposedFirstPassBuffer.CopyColumns(
this.workerHeight - this.windowBandHeight,
0,
this.windowBandHeight);
this.currentWindow = new RowInterval(minY, maxY);
this.CalculateFirstPassValues(this.currentWindow);
// Calculate the remainder:
this.CalculateFirstPassValues(this.currentWindow.Slice(this.windowBandHeight));
}
private void CalculateFirstPassValues(RowInterval window)
private void CalculateFirstPassValues(RowInterval calculationInterval)
{
Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan();
for (int y = window.Min; y < window.Max; y++)
for (int y = calculationInterval.Min; y < calculationInterval.Max; y++)
{
Span<TPixel> sourceRow = this.source.GetRowSpan(y);
@ -166,7 +175,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.conversionModifiers);
// ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top];
Span<Vector4> firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - window.Min);
Span<Vector4> firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - this.currentWindow.Min);
for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++)
{

23
tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

@ -155,5 +155,28 @@ namespace SixLabors.ImageSharp.Tests.Memory
}
}
}
[Fact]
public void CopyColumns_InvokeMultipleTimes()
{
Random rnd = new Random(123);
using (Buffer2D<float> b = this.MemoryAllocator.Allocate2D<float>(100, 100))
{
rnd.RandomFill(b.Span, 0, 1);
b.CopyColumns(0, 50, 22);
b.CopyColumns(0, 50, 22);
for (int y = 0; y < b.Height; y++)
{
Span<float> row = b.GetRowSpan(y);
Span<float> s = row.Slice(0, 22);
Span<float> d = row.Slice(50, 22);
Xunit.Assert.True(s.SequenceEqual(d));
}
}
}
}
}
Loading…
Cancel
Save