From c86551021a6b869f50e90a76b3a5ca2d9b858c4b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 17:47:35 +0200 Subject: [PATCH] simplify ResizeWorker logic --- src/ImageSharp/Memory/RowInterval.cs | 1 - .../Transforms/Resize/ResizeProcessor.cs | 18 +++++---- .../Transforms/Resize/ResizeWorker.cs | 37 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 7e144e37c5..3ee7ae774d 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -38,7 +38,6 @@ namespace SixLabors.ImageSharp.Memory /// public int Height => this.Max - this.Min; - public static bool operator ==(RowInterval left, RowInterval right) { return left.Equals(right); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 63dd5efca0..e75f6014ab 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int startY = this.TargetRectangle.Y; int startX = this.TargetRectangle.X; - var destWorkingRect = Rectangle.Intersect( + var targetWorkingRect = Rectangle.Intersect( this.TargetRectangle, new Rectangle(0, 0, width, height)); @@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; ParallelHelper.IterateRows( - destWorkingRect, + targetWorkingRect, configuration, rows => { @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); - for (int x = destWorkingRect.Left; x < destWorkingRect.Right; x++) + for (int x = targetWorkingRect.Left; x < targetWorkingRect.Right; x++) { // X coordinates of source points targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; @@ -237,8 +237,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); - // If we want to reintroduce processing: - // it's possible to launch multiple workers for different regions of the image + // To reintroduce parallel processing, we to launch multiple workers + // for different row intervals of the image. using (var worker = new ResizeWorker( configuration, sourceArea, @@ -246,11 +246,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.horizontalKernelMap, this.verticalKernelMap, width, - destWorkingRect, - startX)) + targetWorkingRect, + this.TargetRectangle.Location)) { worker.Initialize(); - worker.FillDestinationPixels(destWorkingRect.Top, destWorkingRect.Bottom, startY, destination.PixelBuffer); + + var workingInterval = new RowInterval(targetWorkingRect.Top, targetWorkingRect.Bottom); + worker.FillDestinationPixels(workingInterval, destination.PixelBuffer); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 66a17e2d76..339e8a3b2c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class ResizeWorker : IDisposable where TPixel : struct, IPixel { - private readonly Buffer2D buffer; + private readonly Buffer2D transposedFirstPassBuffer; private readonly Configuration configuration; @@ -29,8 +29,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly Rectangle sourceRectangle; - private readonly int startX; - private readonly IMemoryOwner tempRowBuffer; private readonly IMemoryOwner tempColumnBuffer; @@ -39,7 +37,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly int destWidth; - private readonly Rectangle destWorkingRect; + private readonly Rectangle targetWorkingRect; + + private readonly Point targetOrigin; private readonly int windowBandDiameter; @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ResizeKernelMap horizontalKernelMap, ResizeKernelMap verticalKernelMap, int destWidth, - Rectangle destWorkingRect, - int startX) + Rectangle targetWorkingRect, + Point targetOrigin) { this.configuration = configuration; this.source = source; @@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.horizontalKernelMap = horizontalKernelMap; this.verticalKernelMap = verticalKernelMap; this.destWidth = destWidth; - this.destWorkingRect = destWorkingRect; - this.startX = startX; + this.targetWorkingRect = targetWorkingRect; + this.targetOrigin = targetOrigin; this.windowBandDiameter = verticalKernelMap.MaxDiameter; @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.windowHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandDiameter); - this.buffer = configuration.MemoryAllocator.Allocate2D( + this.transposedFirstPassBuffer = configuration.MemoryAllocator.Allocate2D( this.windowHeight, destWidth, AllocationOptions.Clean); @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public void Dispose() { - this.buffer.Dispose(); + this.transposedFirstPassBuffer.Dispose(); this.tempRowBuffer.Dispose(); this.tempColumnBuffer.Dispose(); } @@ -97,23 +97,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); + return this.transposedFirstPassBuffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); } - public void Initialize() { this.CalculateFirstPassValues(this.currentWindow); } - public void FillDestinationPixels(int minY, int maxY, int startY, Buffer2D destination) + public void FillDestinationPixels(RowInterval rowInterval, Buffer2D destination) { Span tempColSpan = this.tempColumnBuffer.GetSpan(); - for (int y = minY; y < maxY; y++) + for (int y = rowInterval.Min; y < rowInterval.Max; y++) { // Ensure offsets are normalized for cropping and padding. - ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - this.targetOrigin.Y); while (kernel.StartIndex + kernel.Length > this.currentWindow.Max) { @@ -141,7 +140,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] private Span GetColumnSpan(int x) { - return this.buffer.GetRowSpan(x); + return this.transposedFirstPassBuffer.GetRowSpan(x); } private void Slide() @@ -166,11 +165,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers); // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.buffer.Span.Slice(y - window.Min); + Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - window.Min); - for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) + for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++) { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.targetOrigin.X); firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan); // Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan);