From 08ebbf5ab7a2f867fde7aed19bdfe5a3284d9425 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 7 Oct 2018 01:41:26 +0200 Subject: [PATCH] separate PreMultiply from Convonution for rows --- src/ImageSharp/Common/Helpers/ImageMaths.cs | 19 +++++++++++++++++++ .../Processors/Transforms/ResizeKernel.cs | 10 +++++----- .../Processors/Transforms/ResizeProcessor.cs | 6 +++--- .../Helpers/ImageMathsTests.cs | 15 +++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index a318d1941..6accad43f 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -298,5 +298,24 @@ namespace SixLabors.ImageSharp v *= s; } } + + /// + /// Revers + /// + /// + /// The span of vectors + public static void UnPremultiply(Span vectors) + { + // TODO: This method can be AVX2 optimized using Vector + 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; + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs index f149523fc..a69ceea5c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ConvolvePremultipliedRows(Span rowSpan, int sourceX) + public Vector4 ConvolveRows(Span 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 /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ConvolvePremultipliedExpandedRows(Span rowSpan, int sourceX) + public Vector4 ConvolveExpandRows(Span 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; } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 52ed222ca..2643206b4 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -142,7 +142,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public bool Compand { get; } - /// protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { @@ -254,6 +253,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Span tempRowSpan = tempRowBuffer.Span; PixelOperations.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); } } } diff --git a/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs b/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs index 51b407f86..3f41a9955 100644 --- a/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs +++ b/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! } } \ No newline at end of file