From b26ae165e58785c727d2309e84d2442c032ca470 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 2 Dec 2017 00:25:02 +1100 Subject: [PATCH] Performance improvements in loop --- .../Processors/Transforms/AffineProcessor.cs | 38 +++++++++++-------- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 6 +-- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs index cea7f5953a..3dbcf796fc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; -using System.Runtime.CompilerServices; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Helpers; @@ -109,6 +108,8 @@ namespace SixLabors.ImageSharp.Processing.Processors float yScale = yRadiusScale.scale; float xRadius = xRadiusScale.radius; float yRadius = yRadiusScale.radius; + IResampler sampler = this.Sampler; + var maxSource = new Vector4(maxSourceX, maxSourceY, maxSourceX, maxSourceY); Parallel.For( 0, @@ -121,36 +122,41 @@ namespace SixLabors.ImageSharp.Processing.Processors { // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. - var point = PointF.Transform(new PointF(x, y), matrix); - int maxX = (int)MathF.Ceiling(point.X + xRadius); - int maxY = (int)MathF.Ceiling(point.Y + yRadius); - int minX = (int)MathF.Floor(point.X - xRadius); - int minY = (int)MathF.Floor(point.Y - yRadius); - - // Clamp sampling pixels to the source image edge - maxX = maxX.Clamp(0, maxSourceX); - minX = minX.Clamp(0, maxSourceX); - maxY = maxY.Clamp(0, maxSourceY); - minY = minY.Clamp(0, maxSourceY); + var point = Vector2.Transform(new Vector2(x, y), matrix); + + // Clamp sampling pixel radial extents to the source image edges + var extents = new Vector4( + MathF.Ceiling(point.X + xRadius), + MathF.Ceiling(point.Y + yRadius), + MathF.Floor(point.X - xRadius), + MathF.Floor(point.Y - yRadius)); + + extents = Vector4.Clamp(extents, Vector4.Zero, maxSource); + + int maxX = (int)extents.X; + int maxY = (int)extents.Y; + int minX = (int)extents.Z; + int minY = (int)extents.W; if (minX == maxX || minY == maxY) { continue; } - // It appears these have to be calculated manually. + // It appears these have to be calculated on-the-fly. // Using the precalculated weights give the wrong values. - // TODO: Find a way to speed this up. + // TODO: Find a way to speed this up if we can. Vector4 sum = Vector4.Zero; for (int i = minX; i <= maxX; i++) { - float weightX = this.Sampler.GetValue((i - point.X) / xScale); + float weightX = sampler.GetValue((i - point.X) / xScale); for (int j = minY; j <= maxY; j++) { - float weightY = this.Sampler.GetValue((j - point.Y) / yScale); + float weightY = sampler.GetValue((j - point.Y) / yScale); sum += source[i, j].ToVector4() * weightX * weightY; } } + ref TPixel dest = ref destRow[x]; dest.PackFromVector4(sum); } diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 2f45e4c83a..eb60aa5fe4 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -17,9 +17,9 @@ - - - + + +