From fd7c5db66bb0a6d740bd8b0117fa78d85dc78bad Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 18:37:16 +0200 Subject: [PATCH] ResizeWindow refactor 1 --- .../Transforms/Resize/ResizeProcessor.cs | 115 ++---------------- .../Transforms/Resize/ResizeWindow.cs | 97 +++++++++++++++ 2 files changed, 106 insertions(+), 106 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 429b709ee3..707be1ec9d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -195,19 +195,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int sourceX = sourceRectangle.X; int sourceY = sourceRectangle.Y; int startY = this.TargetRectangle.Y; - int endY = this.TargetRectangle.Bottom; int startX = this.TargetRectangle.X; - int endX = this.TargetRectangle.Right; - int minX = Math.Max(0, startX); - int maxX = Math.Min(width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(height, endY); + var workingRect = Rectangle.Intersect( + this.TargetRectangle, + new Rectangle(0, 0, width, height)); if (this.Sampler is NearestNeighborResampler) { - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - // Scaling factors float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; @@ -224,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); - for (int x = minX; x < maxX; x++) + for (int x = workingRect.Left; x < workingRect.Right; x++) { // X coordinates of source points targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; @@ -244,29 +239,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. - //using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(sourceHeight, width)) - - using (var resizeWindow = new ResizeWindowOld( + using (var resizeWindow = new ResizeWindow( configuration, sourceRectangle, conversionModifiers, this.horizontalKernelMap, this.verticalKernelMap, - sourceHeight, width, - minX, - maxX, + workingRect, startX)) - using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(source.Width, width))) + using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(sourceRectangle.Width, width))) { - Span tempRowSpan = tempBuffer.GetSpan().Slice(sourceX, source.Width - sourceX); + Span tempRowSpan = tempBuffer.GetSpan(); resizeWindow.Initialize(source.PixelBuffer, tempRowSpan); // Now process the rows. Span tempColSpan = tempBuffer.GetSpan().Slice(0, width); - for (int y = minY; y < maxY; y++) + for (int y = workingRect.Top; y < workingRect.Bottom; y++) { // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); @@ -299,92 +290,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.verticalKernelMap = null; } } - - class ResizeWindowOld : IDisposable - { - private readonly Buffer2D buffer; - - private readonly Configuration configuration; - - private readonly Rectangle sourceRectangle; - - private readonly PixelConversionModifiers conversionModifiers; - - private readonly ResizeKernelMap horizontalKernelMap; - - private readonly ResizeKernelMap verticalKernelMap; - - private readonly int minX; - - private readonly int maxX; - - private readonly int startX; - - public ResizeWindowOld( - Configuration configuration, - Rectangle sourceRectangle, - PixelConversionModifiers conversionModifiers, - ResizeKernelMap horizontalKernelMap, - ResizeKernelMap verticalKernelMap, - int sourceHeight, - int destWidth, - int minX, - int maxX, - int startX) - { - this.configuration = configuration; - this.sourceRectangle = sourceRectangle; - this.conversionModifiers = conversionModifiers; - this.horizontalKernelMap = horizontalKernelMap; - this.verticalKernelMap = verticalKernelMap; - this.minX = minX; - this.maxX = maxX; - this.startX = startX; - this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); - - this.Top = sourceRectangle.Top; - - this.Bottom = sourceRectangle.Bottom; - } - - public int Top { get; private set; } - - public int Bottom { get; private set; } - - public void Initialize( - Buffer2D source, - Span tempRowSpan) - where TPixel : struct, IPixel - { - for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) - { - Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); - - PixelOperations.Instance.ToVector4( - this.configuration, - sourceRow, - tempRowSpan, - this.conversionModifiers); - - ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; - - for (int x = this.minX; x < this.maxX; x++) - { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); - Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnSpan(int x) - { - return this.buffer.GetRowSpan(x); - } - - public void Dispose() - { - this.buffer.Dispose(); - } - } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs new file mode 100644 index 0000000000..130dd93a4b --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -0,0 +1,97 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + class ResizeWindow : IDisposable + { + private readonly Buffer2D buffer; + + private readonly Configuration configuration; + + private readonly Rectangle sourceRectangle; + + private readonly PixelConversionModifiers conversionModifiers; + + private readonly ResizeKernelMap horizontalKernelMap; + + private readonly ResizeKernelMap verticalKernelMap; + + private readonly Rectangle workingRectangle; + + private readonly int startX; + + public ResizeWindow( + Configuration configuration, + Rectangle sourceRectangle, + PixelConversionModifiers conversionModifiers, + ResizeKernelMap horizontalKernelMap, + ResizeKernelMap verticalKernelMap, + int destWidth, + Rectangle workingRectangle, + int startX) + { + this.configuration = configuration; + this.sourceRectangle = sourceRectangle; + this.conversionModifiers = conversionModifiers; + this.horizontalKernelMap = horizontalKernelMap; + this.verticalKernelMap = verticalKernelMap; + this.workingRectangle = workingRectangle; + this.startX = startX; + this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); + + this.Top = sourceRectangle.Top; + + this.Bottom = sourceRectangle.Bottom; + } + + public int Top { get; private set; } + + public int Bottom { get; private set; } + + public void Initialize( + Buffer2D source, + Span tempRowSpan) + where TPixel : struct, IPixel + { + for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) + { + Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); + + PixelOperations.Instance.ToVector4( + this.configuration, + sourceRow, + tempRowSpan, + this.conversionModifiers); + + ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; + + for (int x = this.workingRectangle.Left; x < this.workingRectangle.Right; x++) + { + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); + Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnSpan(int x) + { + return this.buffer.GetRowSpan(x); + } + + public void Dispose() + { + this.buffer.Dispose(); + } + } +} \ No newline at end of file