diff --git a/src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs b/src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs
index 380545d70..3ff174c5d 100644
--- a/src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs
+++ b/src/ImageSharp/Common/Memory/PinnedImageBuffer{T}.cs
@@ -53,7 +53,14 @@ namespace ImageSharp
/// The x coordinate (row)
/// The y coordinate (position at row)
/// A reference to the element.
- 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];
+ }
+ }
///
/// Creates a clean instance of initializing it's elements with 'default(T)'.
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
index c7386487a..785a1f20c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
@@ -51,19 +51,22 @@ namespace ImageSharp.Processing.Processors
///
/// The input span of vectors
/// The weighted sum
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeWeightedRowSum(BufferSpan 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
///
/// The input span of vectors
/// The weighted sum
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeExpandedWeightedRowSum(BufferSpan 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
/// The buffer of input vectors in row first order
/// The column position
/// The weighted sum
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ComputeWeightedColumnSum(PinnedImageBuffer firstPassPixels, int x)
{
float* verticalValues = this.Ptr;
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
index 944e245ac..0e1a215e0 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
+++ b/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 tempRowBuffer = new PinnedBuffer(sourcePixels.Width))
- {
- BufferSpan sourceRow = sourcePixels.GetRowSpan(y);
-
- BulkPixelOperations.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 tempRowBuffer = new PinnedBuffer(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 sourceRow = sourcePixels.GetRowSpan(y);
+
+ BulkPixelOperations.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);
diff --git a/tests/ImageSharp.Sandbox46/Program.cs b/tests/ImageSharp.Sandbox46/Program.cs
index 467663a53..dad603523 100644
--- a/tests/ImageSharp.Sandbox46/Program.cs
+++ b/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());
diff --git a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs b/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs
index 35994e028..a95b196b7 100644
--- a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs
+++ b/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,