Browse Source

Span<T>!!

pull/386/head
James Jackson-South 9 years ago
parent
commit
13f73a963a
  1. 2
      src/ImageSharp/Memory/Buffer{T}.cs
  2. 35
      src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs

2
src/ImageSharp/Memory/Buffer{T}.cs

@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Buffer<T> CreateClean(int count) public static Buffer<T> CreateClean(int count)
{ {
Buffer<T> buffer = new Buffer<T>(count); var buffer = new Buffer<T>(count);
buffer.Clear(); buffer.Clear();
return buffer; return buffer;
} }

35
src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs

@ -103,6 +103,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
int xLength = (int)MathF.Ceiling((radius.X * 2) + 2); int xLength = (int)MathF.Ceiling((radius.X * 2) + 2);
int yLength = (int)MathF.Ceiling((radius.Y * 2) + 2); int yLength = (int)MathF.Ceiling((radius.Y * 2) + 2);
using (var yBuffer = new Buffer2D<float>(yLength, height))
using (var xBuffer = new Buffer2D<float>(xLength, height))
{
Parallel.For( Parallel.For(
0, 0,
height, height,
@ -110,9 +113,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
y => y =>
{ {
Span<TPixel> destRow = destination.GetPixelRowSpan(y); Span<TPixel> destRow = destination.GetPixelRowSpan(y);
using (var yBuffer = new Buffer<float>(yLength)) Span<float> ySpan = yBuffer.GetRowSpan(y);
using (var xBuffer = new Buffer<float>(xLength)) Span<float> xSpan = xBuffer.GetRowSpan(y);
{
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
// Use the single precision position to calculate correct bounding pixels // Use the single precision position to calculate correct bounding pixels
@ -148,38 +151,38 @@ namespace SixLabors.ImageSharp.Processing.Processors
// It appears these have to be calculated on-the-fly. // It appears these have to be calculated on-the-fly.
// Precalulating transformed weights would require prior knowledge of every transformed pixel location // Precalulating transformed weights would require prior knowledge of every transformed pixel location
// since they can be at sub-pixel positions. // since they can be at sub-pixel positions on both axis.
// I've optimized where I can but am always open to suggestions. // I've optimized where I can but am always open to suggestions.
// //
// Create and normalize the y-weights // Create and normalize the y-weights
if (yScale > 1) if (yScale > 1)
{ {
CalculateWeightsDown(top, bottom, minY, maxY, point.Y, sampler, yScale, yBuffer); CalculateWeightsDown(top, bottom, minY, maxY, point.Y, sampler, yScale, ySpan);
} }
else else
{ {
CalculateWeightsScaleUp(minY, maxY, point.Y, sampler, yBuffer); CalculateWeightsScaleUp(minY, maxY, point.Y, sampler, ySpan);
} }
// Create and normalize the x-weights // Create and normalize the x-weights
if (xScale > 1) if (xScale > 1)
{ {
CalculateWeightsDown(left, right, minX, maxX, point.X, sampler, xScale, xBuffer); CalculateWeightsDown(left, right, minX, maxX, point.X, sampler, xScale, xSpan);
} }
else else
{ {
CalculateWeightsScaleUp(minX, maxX, point.X, sampler, xBuffer); CalculateWeightsScaleUp(minX, maxX, point.X, sampler, xSpan);
} }
// Now multiply the results against the offsets // Now multiply the results against the offsets
Vector4 sum = Vector4.Zero; Vector4 sum = Vector4.Zero;
for (int yy = 0, j = minY; j <= maxY; j++, yy++) for (int yy = 0, j = minY; j <= maxY; j++, yy++)
{ {
float yWeight = yBuffer[yy]; float yWeight = ySpan[yy];
for (int xx = 0, i = minX; i <= maxX; i++, xx++) for (int xx = 0, i = minX; i <= maxX; i++, xx++)
{ {
float xWeight = xBuffer[xx]; float xWeight = xSpan[xx];
sum += source[i, j].ToVector4() * xWeight * yWeight; sum += source[i, j].ToVector4() * xWeight * yWeight;
} }
} }
@ -187,9 +190,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
ref TPixel dest = ref destRow[x]; ref TPixel dest = ref destRow[x];
dest.PackFromVector4(sum); dest.PackFromVector4(sum);
} }
}
}); });
} }
}
/// <summary> /// <summary>
/// Gets a transform matrix adjusted to center upon the target image bounds. /// Gets a transform matrix adjusted to center upon the target image bounds.
@ -206,7 +209,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
} }
/// <summary> /// <summary>
/// Calculated the weights for the given point. This method uses more samples than the upscaled version to ensure edge pixels are correctly rendered. /// Calculated the weights for the given point.
/// This method uses more samples than the upscaled version to ensure edge pixels are correctly rendered.
/// Additionally the weights are nomalized. /// Additionally the weights are nomalized.
/// </summary> /// </summary>
/// <param name="min">The minimum sampling offset</param> /// <param name="min">The minimum sampling offset</param>
@ -218,7 +222,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="scale">The transformed image scale relative to the source</param> /// <param name="scale">The transformed image scale relative to the source</param>
/// <param name="weights">The collection of weights</param> /// <param name="weights">The collection of weights</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CalculateWeightsDown(int min, int max, int sourceMin, int sourceMax, float point, IResampler sampler, float scale, Buffer<float> weights) private static void CalculateWeightsDown(int min, int max, int sourceMin, int sourceMax, float point, IResampler sampler, float scale, Span<float> weights)
{ {
float sum = 0; float sum = 0;
ref float weightsBaseRef = ref weights[0]; ref float weightsBaseRef = ref weights[0];
@ -253,8 +257,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
} }
/// <summary> /// <summary>
/// Calculated the weights for the given point. This method uses more samples than the upscaled version to ensure edge pixels are correctly rendered. /// Calculated the weights for the given point.
/// Additionally the weights are nomalized.
/// </summary> /// </summary>
/// <param name="sourceMin">The minimum source bounds</param> /// <param name="sourceMin">The minimum source bounds</param>
/// <param name="sourceMax">The maximum source bounds</param> /// <param name="sourceMax">The maximum source bounds</param>
@ -262,7 +265,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="sampler">The sampler</param> /// <param name="sampler">The sampler</param>
/// <param name="weights">The collection of weights</param> /// <param name="weights">The collection of weights</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CalculateWeightsScaleUp(int sourceMin, int sourceMax, float point, IResampler sampler, Buffer<float> weights) private static void CalculateWeightsScaleUp(int sourceMin, int sourceMax, float point, IResampler sampler, Span<float> weights)
{ {
ref float weightsBaseRef = ref weights[0]; ref float weightsBaseRef = ref weights[0];
for (int x = 0, i = sourceMin; i <= sourceMax; i++, x++) for (int x = 0, i = sourceMin; i <= sourceMax; i++, x++)

Loading…
Cancel
Save