Browse Source

separate PreMultiply from Convonution for rows

pull/731/head
Anton Firszov 7 years ago
parent
commit
c1afe359db
  1. 19
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  2. 10
      src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs
  3. 6
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  4. 15
      tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs

19
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -298,5 +298,24 @@ namespace SixLabors.ImageSharp
v *= s;
}
}
/// <summary>
/// Revers <see cref="Premultiply"/>
/// </summary>
/// <seealso cref="Vector4Extensions.UnPremultiply"/>
/// <param name="vectors">The span of vectors</param>
public static void UnPremultiply(Span<Vector4> vectors)
{
// TODO: This method can be AVX2 optimized using Vector<float>
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors);
for (int i = 0; i < vectors.Length; i++)
{
ref Vector4 v = ref Unsafe.Add(ref baseRef, i);
var s = new Vector4(1 / v.W);
s.W = 1;
v *= s;
}
}
}
}

10
src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs

@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <param name="sourceX">The source row position.</param>
/// <returns>The weighted sum</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ConvolvePremultipliedRows(Span<Vector4> rowSpan, int sourceX)
public Vector4 ConvolveRows(Span<Vector4> rowSpan, int sourceX)
{
ref float horizontalValues = ref this.GetStartReference();
int left = this.Left;
@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
float weight = Unsafe.Add(ref horizontalValues, i);
Vector4 v = Unsafe.Add(ref vecPtr, i);
result += v.Premultiply() * weight;
result += v * weight;
}
return result;
@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <param name="sourceX">The source row position.</param>
/// <returns>The weighted sum</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ConvolvePremultipliedExpandedRows(Span<Vector4> rowSpan, int sourceX)
public Vector4 ConvolveExpandRows(Span<Vector4> rowSpan, int sourceX)
{
ref float horizontalValues = ref this.GetStartReference();
int left = this.Left;
@ -118,10 +118,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
float weight = Unsafe.Add(ref horizontalValues, i);
Vector4 v = Unsafe.Add(ref vecPtr, i);
result += v.Premultiply().Expand() * weight;
result += v.Expand() * weight;
}
return result.UnPremultiply();
return result;
}
/// <summary>

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

@ -142,7 +142,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// </summary>
public bool Compand { get; }
/// <inheritdoc/>
protected override Image<TPixel> CreateDestination(Image<TPixel> source, Rectangle sourceRectangle)
{
@ -254,6 +253,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Span<Vector4> tempRowSpan = tempRowBuffer.Span;
PixelOperations<TPixel>.Instance.ToVector4(sourceRow, tempRowSpan, sourceRow.Length);
ImageMaths.Premultiply(tempRowSpan);
if (this.Compand)
{
@ -261,7 +261,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
ResizeKernel window = this.horizontalKernelMap.Kernels[x - startX];
Unsafe.Add(ref firstPassRow, x) =
window.ConvolvePremultipliedExpandedRows(tempRowSpan, sourceX);
window.ConvolveExpandRows(tempRowSpan, sourceX).UnPremultiply();
}
}
else
@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
ResizeKernel window = this.horizontalKernelMap.Kernels[x - startX];
Unsafe.Add(ref firstPassRow, x) =
window.ConvolvePremultipliedRows(tempRowSpan, sourceX);
window.ConvolveRows(tempRowSpan, sourceX);
}
}
}

15
tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs

@ -54,6 +54,21 @@ namespace SixLabors.ImageSharp.Tests.Helpers
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f));
}
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(30)]
public void UnPremultiply_VectorSpan(int length)
{
var rnd = new Random(42);
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1);
Vector4[] expected = source.Select(v => v.UnPremultiply()).ToArray();
ImageMaths.UnPremultiply(source);
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f));
}
// TODO: We need to test all ImageMaths methods!
}
}
Loading…
Cancel
Save