Browse Source

improved, sequential ResizeProcessor

af/merge-core
Anton Firszov 9 years ago
parent
commit
1042a97b72
  1. 9
      src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs
  2. 19
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
  3. 104
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  4. 9
      tests/ImageSharp.Sandbox46/Program.cs
  5. 2
      tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs

9
src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs

@ -53,7 +53,14 @@ namespace ImageSharp
/// <param name="x">The x coordinate (row)</param>
/// <param name="y">The y coordinate (position at row)</param>
/// <returns>A reference to the element.</returns>
public ref T this[int x, int y] => ref this.Array[(this.Width * y) + x];
public ref T this[int x, int y]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return ref this.Array[(this.Width * y) + x];
}
}
/// <summary>
/// Creates a clean instance of <see cref="PinnedImageBuffer{T}"/> initializing it's elements with 'default(T)'.

19
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs

@ -51,19 +51,22 @@ namespace ImageSharp.Processing.Processors
/// </summary>
/// <param name="rowSpan">The input span of vectors</param>
/// <returns>The weighted sum</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeWeightedRowSum(BufferSpan<Vector4> rowSpan)
{
float* horizontalValues = this.Ptr;
int left = this.Left;
Vector4* vecPtr = (Vector4*)rowSpan.PointerAtOffset;
vecPtr += left;
// Destination color components
Vector4 result = Vector4.Zero;
for (int i = 0; i < this.Length; i++)
{
float xw = horizontalValues[i];
int index = left + i;
result += rowSpan[index] * xw;
float weight = horizontalValues[i];
result += (*vecPtr) * weight;
vecPtr++;
}
return result;
@ -75,19 +78,22 @@ namespace ImageSharp.Processing.Processors
/// </summary>
/// <param name="rowSpan">The input span of vectors</param>
/// <returns>The weighted sum</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeExpandedWeightedRowSum(BufferSpan<Vector4> rowSpan)
{
float* horizontalValues = this.Ptr;
int left = this.Left;
Vector4* vecPtr = (Vector4*)rowSpan.PointerAtOffset;
vecPtr += left;
// Destination color components
Vector4 result = Vector4.Zero;
for (int i = 0; i < this.Length; i++)
{
float xw = horizontalValues[i];
int index = left + i;
result += rowSpan[index].Expand() * xw;
float weight = horizontalValues[i];
result += (*vecPtr).Expand() * weight;
vecPtr++;
}
return result;
@ -100,6 +106,7 @@ namespace ImageSharp.Processing.Processors
/// <param name="firstPassPixels">The buffer of input vectors in row first order</param>
/// <param name="x">The column position</param>
/// <returns>The weighted sum</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeWeightedColumnSum(PinnedImageBuffer<Vector4> firstPassPixels, int x)
{
float* verticalValues = this.Ptr;

104
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -110,76 +110,64 @@ namespace ImageSharp.Processing.Processors
{
firstPassPixels.Clear();
Parallel.For(
0,
sourceRectangle.Bottom,
this.ParallelOptions,
y =>
{
// TODO: Without Parallel.For() this buffer object could be reused:
using (PinnedBuffer<Vector4> tempRowBuffer = new PinnedBuffer<Vector4>(sourcePixels.Width))
{
BufferSpan<TColor> sourceRow = sourcePixels.GetRowSpan(y);
BulkPixelOperations<TColor>.Instance.ToVector4(
sourceRow,
tempRowBuffer,
sourceRow.Length);
if (this.Compand)
{
for (int x = minX; x < maxX; x++)
{
WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer);
}
}
else
{
for (int x = minX; x < maxX; x++)
{
WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer);
}
}
}
});
// Now process the rows.
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
using (PinnedBuffer<Vector4> tempRowBuffer = new PinnedBuffer<Vector4>(sourcePixels.Width))
{
for (int y = 0; y < sourceRectangle.Bottom; y++)
{
// Ensure offsets are normalised for cropping and padding.
WeightsWindow window = this.VerticalWeights.Weights[y - startY];
BufferSpan<TColor> sourceRow = sourcePixels.GetRowSpan(y);
BulkPixelOperations<TColor>.Instance.ToVector4(sourceRow, tempRowBuffer, sourceRow.Length);
if (this.Compand)
{
for (int x = 0; x < width; x++)
for (int x = minX; x < maxX; x++)
{
// Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);
destination = destination.Compress();
TColor d = default(TColor);
d.PackFromVector4(destination);
targetPixels[x, y] = d;
WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer);
}
}
else
{
for (int x = 0; x < width; x++)
for (int x = minX; x < maxX; x++)
{
// Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);
TColor d = default(TColor);
d.PackFromVector4(destination);
targetPixels[x, y] = d;
WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer);
}
}
});
}
}
// Now process the rows.
for (int y = minY; y < maxY; y++)
{
// Ensure offsets are normalised for cropping and padding.
WeightsWindow window = this.VerticalWeights.Weights[y - startY];
if (this.Compand)
{
for (int x = 0; x < width; x++)
{
// Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);
destination = destination.Compress();
TColor d = default(TColor);
d.PackFromVector4(destination);
targetPixels[x, y] = d;
}
}
else
{
for (int x = 0; x < width; x++)
{
// Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);
TColor d = default(TColor);
d.PackFromVector4(destination);
targetPixels[x, y] = d;
}
}
}
}
source.SwapPixelsBuffers(targetPixels);

9
tests/ImageSharp.Sandbox46/Program.cs

@ -38,12 +38,19 @@ namespace ImageSharp.Sandbox46
public static void Main(string[] args)
{
// RunDecodeJpegProfilingTests();
// RunToVector4ProfilingTest();
RunToVector4ProfilingTest();
RunResizeProfilingTest();
Console.ReadLine();
}
private static void RunResizeProfilingTest()
{
ResizeProfilingBenchmarks test = new ResizeProfilingBenchmarks(new ConsoleOutput());
test.ResizeBicubic(2000, 2000);
}
private static void RunToVector4ProfilingTest()
{
BulkPixelOperationsTests.Color tests = new BulkPixelOperationsTests.Color(new ConsoleOutput());

2
tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs

@ -21,7 +21,7 @@ namespace ImageSharp.Tests
[Theory]
[InlineData(100, 100)]
[InlineData(1000, 1000)]
[InlineData(2000, 2000)]
public void ResizeBicubic(int width, int height)
{
this.Measure(this.ExecutionCount,

Loading…
Cancel
Save