From 72a6a7e32103cec0da0ce982149e44c4083498a0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 28 Nov 2018 01:12:17 +0100 Subject: [PATCH] preparations for implementing MosaicKernelMap --- .../Transforms/Resize/ResizeKernel.cs | 12 +- .../Resize/ResizeKernelMap.MosaicKernelMap.cs | 5 + .../Transforms/Resize/ResizeKernelMap.cs | 131 ++++++++++-------- .../KernelMapTests.ReferenceKernelMap.cs | 2 +- .../Processors/Transforms/KernelMapTests.cs | 2 +- 5 files changed, 86 insertions(+), 66 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 1183de7541..b2d7d21167 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -41,9 +41,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Gets the span representing the portion of the that this window covers /// - /// The - [MethodImpl(InliningOptions.ShortMethod)] - public Span GetValues() => new Span(this.bufferPtr, this.Length); + /// The + /// + public Span Values + { + [MethodImpl(InliningOptions.ShortMethod)] + get => new Span(this.bufferPtr, this.Length); + } /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. @@ -53,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Vector4 Convolve(Span rowSpan) { - ref float horizontalValues = ref MemoryMarshal.GetReference(this.GetValues()); + ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); int left = this.Left; ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.MosaicKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.MosaicKernelMap.cs index b815d05cbc..09ae796777 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.MosaicKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.MosaicKernelMap.cs @@ -41,6 +41,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.cornerInterval = cornerInterval; this.period = period; } + + protected override void Initialize() + { + base.Initialize(); + } } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs index 443db72d9e..ebb15d3768 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Returns a for an index value between 0 and destinationSize - 1. + /// Returns a for an index value between 0 and DestinationSize - 1. /// [MethodImpl(InliningOptions.ShortMethod)] public ref ResizeKernel GetKernel(int destIdx) => ref this.kernels[destIdx]; @@ -101,93 +101,104 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms bool useMosaic = 2 * (cornerInterval + period) < destinationSize; + useMosaic = false; + ResizeKernelMap result = useMosaic - ? new ResizeKernelMap( - memoryAllocator, - sampler, - sourceSize, - destinationSize, - destinationSize, - ratio, - scale, - radius) - : new MosaicKernelMap( - memoryAllocator, - sampler, - sourceSize, - destinationSize, - ratio, - scale, - radius, - period, - cornerInterval); - - result.Init(); + ? new MosaicKernelMap( + memoryAllocator, + sampler, + sourceSize, + destinationSize, + ratio, + scale, + radius, + period, + cornerInterval) + : new ResizeKernelMap( + memoryAllocator, + sampler, + sourceSize, + destinationSize, + destinationSize, + ratio, + scale, + radius); + + result.Initialize(); return result; } - protected virtual void Init() + protected virtual void Initialize() { - for (int i = 0; i < this.DestinationSize; i++) + for (int destRowIndex = 0; destRowIndex < this.DestinationSize; destRowIndex++) { - float center = ((i + .5F) * this.ratio) - .5F; + ResizeKernel kernel = this.BuildKernelRow(destRowIndex, destRowIndex); + this.kernels[destRowIndex] = kernel; + } + } - // Keep inside bounds. - int left = (int)MathF.Ceiling(center - this.radius); - if (left < 0) - { - left = 0; - } + private ResizeKernel BuildKernelRow(int destRowIndex, int dataRowIndex) + { + float center = ((destRowIndex + .5F) * this.ratio) - .5F; - int right = (int)MathF.Floor(center + this.radius); - if (right > this.sourceSize - 1) - { - right = this.sourceSize - 1; - } + // Keep inside bounds. + int left = (int)MathF.Ceiling(center - this.radius); + if (left < 0) + { + left = 0; + } - float sum = 0; + int right = (int)MathF.Floor(center + this.radius); + if (right > this.sourceSize - 1) + { + right = this.sourceSize - 1; + } - ResizeKernel kernel = this.CreateKernel(i, left, right); - this.kernels[i] = kernel; + float sum = 0; - ref float kernelBaseRef = ref MemoryMarshal.GetReference(kernel.GetValues()); + ResizeKernel kernel = this.GetKernel(dataRowIndex, left, right); - for (int j = left; j <= right; j++) - { - float value = this.sampler.GetValue((j - center) / this.scale); - sum += value; + ref float kernelBaseRef = ref MemoryMarshal.GetReference(kernel.Values); - // weights[j - left] = weight: - Unsafe.Add(ref kernelBaseRef, j - left) = value; - } + for (int j = left; j <= right; j++) + { + float value = this.sampler.GetValue((j - center) / this.scale); + sum += value; - // Normalize, best to do it here rather than in the pixel loop later on. - if (sum > 0) + // weights[j - left] = weight: + Unsafe.Add(ref kernelBaseRef, j - left) = value; + } + + // Normalize, best to do it here rather than in the pixel loop later on. + if (sum > 0) + { + for (int w = 0; w < kernel.Length; w++) { - for (int w = 0; w < kernel.Length; w++) - { - // weights[w] = weights[w] / sum: - ref float kRef = ref Unsafe.Add(ref kernelBaseRef, w); - kRef /= sum; - } + // weights[w] = weights[w] / sum: + ref float kRef = ref Unsafe.Add(ref kernelBaseRef, w); + kRef /= sum; } } + + return kernel; } /// - /// Slices a weights value at the given positions. + /// Returns a referencing values of + /// at row . /// - private unsafe ResizeKernel CreateKernel(int destIdx, int left, int rightIdx) + private unsafe ResizeKernel GetKernel(int dataRowIndex, int left, int right) { - int length = rightIdx - left + 1; + int length = right - left + 1; if (length > this.data.Width) { - throw new InvalidOperationException($"Error in KernelMap.CreateKernel({destIdx},{left},{rightIdx}): left > this.data.Width"); + throw new InvalidOperationException( + $"Error in KernelMap.CreateKernel({dataRowIndex},{left},{right}): left > this.data.Width"); } - Span rowSpan = this.data.GetRowSpan(destIdx); + Span rowSpan = this.data.GetRowSpan(dataRowIndex); ref float rowReference = ref MemoryMarshal.GetReference(rowSpan); float* rowPtr = (float*)Unsafe.AsPointer(ref rowReference); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.ReferenceKernelMap.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.ReferenceKernelMap.cs index 85a930fb9a..f7c3b27e5a 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.ReferenceKernelMap.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.ReferenceKernelMap.cs @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public static implicit operator ReferenceKernel(ResizeKernel orig) { - return new ReferenceKernel(orig.Left, orig.GetValues().ToArray()); + return new ReferenceKernel(orig.Left, orig.Values.ToArray()); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.cs index 4d005576c2..7b997e33f2 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/KernelMapTests.cs @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms Assert.Equal(referenceKernel.Length, kernel.Length); Assert.Equal(referenceKernel.Left, kernel.Left); float[] expectedValues = referenceKernel.Values; - Span actualValues = kernel.GetValues(); + Span actualValues = kernel.Values; Assert.Equal(expectedValues.Length, actualValues.Length);