From cbf476e34e254bde983d1b60df60c94e200e36cc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 10 Aug 2016 14:29:21 +1000 Subject: [PATCH] Sampler performance optimizations Former-commit-id: 57f9665225227b25a9dc53357985097001df37c8 Former-commit-id: 0ba692a70a1480b5de88015bb0660a2471f63ec3 Former-commit-id: 055257264bc4063a23db7c056a7cfa7a7c4394be --- .../Samplers/Processors/EntropyCropProcessor.cs | 16 ++++++++-------- .../Samplers/Processors/Matrix3x2Processor.cs | 8 ++------ .../Samplers/Processors/RotateFlipProcessor.cs | 16 +++------------- .../Samplers/Processors/RotateProcessor.cs | 13 +++++++------ .../Samplers/Processors/SkewProcessor.cs | 6 ++++-- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs index fea02e350..8d4ad6885 100644 --- a/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs @@ -24,7 +24,7 @@ namespace ImageProcessorCore.Processors private Rectangle cropRectangle; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. /// @@ -74,21 +74,21 @@ namespace ImageProcessorCore.Processors int startX = this.cropRectangle.X; int endX = this.cropRectangle.Right; + int minY = Math.Max(targetY, startY); + int maxY = Math.Min(targetBottom, endY); + using (IPixelAccessor sourcePixels = source.Lock()) using (IPixelAccessor targetPixels = target.Lock()) { Parallel.For( - startY, - endY, + minY, + maxY, this.ParallelOptions, y => { - if (y >= targetY && y < targetBottom) + for (int x = startX; x < endX; x++) { - for (int x = startX; x < endX; x++) - { - targetPixels[x - startX, y - targetY] = sourcePixels[x, y]; - } + targetPixels[x - startX, y - targetY] = sourcePixels[x, y]; } this.OnRowProcessed(); diff --git a/src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs b/src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs index bc95f4454..7d5f53628 100644 --- a/src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs @@ -19,8 +19,6 @@ namespace ImageProcessorCore.Processors /// /// Creates a new target to contain the results of the matrix transform. /// - /// The pixel format. - /// The packed format. long, float. /// Target image to apply the process to. /// The source rectangle. /// The processing matrix. @@ -37,8 +35,6 @@ namespace ImageProcessorCore.Processors /// /// Gets a transform matrix adjusted to center upon the target image bounds. /// - /// The pixel format. - /// The packed format. long, float. /// Target image to apply the process to. /// The source image. /// The transform matrix. @@ -47,8 +43,8 @@ namespace ImageProcessorCore.Processors /// protected static Matrix3x2 GetCenteredMatrix(ImageBase target, ImageBase source, Matrix3x2 matrix) { - Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-target.Width / 2f, -target.Height / 2f); - Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width / 2f, source.Height / 2f); + Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-target.Width * .5F, -target.Height * .5F); + Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F); return (translationToTargetCenter * matrix) * translateToSourceCenter; } } diff --git a/src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs index f1233a553..764e68de6 100644 --- a/src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs @@ -18,7 +18,7 @@ namespace ImageProcessorCore.Processors where TP : struct { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The used to perform rotation. /// The used to perform flipping. @@ -72,8 +72,6 @@ namespace ImageProcessorCore.Processors /// /// Rotates the image 270 degrees clockwise at the centre point. /// - /// The pixel format. - /// The packed format. long, float. /// The target image. /// The source image. private void Rotate270(ImageBase target, ImageBase source) @@ -110,8 +108,6 @@ namespace ImageProcessorCore.Processors /// /// Rotates the image 180 degrees clockwise at the centre point. /// - /// The pixel format. - /// The packed format. long, float. /// The target image. /// The source image. private void Rotate180(ImageBase target, ImageBase source) @@ -143,8 +139,6 @@ namespace ImageProcessorCore.Processors /// /// Rotates the image 90 degrees clockwise at the centre point. /// - /// The pixel format. - /// The packed format. long, float. /// The target image. /// The source image. private void Rotate90(ImageBase target, ImageBase source) @@ -179,14 +173,12 @@ namespace ImageProcessorCore.Processors /// Swaps the image at the X-axis, which goes horizontally through the middle /// at half the height of the image. /// - /// The pixel format. - /// The packed format. long, float. /// Target image to apply the process to. private void FlipX(ImageBase target) { int width = target.Width; int height = target.Height; - int halfHeight = (int)Math.Ceiling(target.Height * .5); + int halfHeight = (int)Math.Ceiling(target.Height * .5F); Image temp = new Image(width, height); temp.ClonePixels(width, height, target.Pixels); @@ -215,14 +207,12 @@ namespace ImageProcessorCore.Processors /// Swaps the image at the Y-axis, which goes vertically through the middle /// at half of the width of the image. /// - /// The pixel format. - /// The packed format. long, float. /// Target image to apply the process to. private void FlipY(ImageBase target) { int width = target.Width; int height = target.Height; - int halfWidth = (int)Math.Ceiling(width / 2d); + int halfWidth = (int)Math.Ceiling(width * .5F); Image temp = new Image(width, height); temp.ClonePixels(width, height, target.Pixels); diff --git a/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs index 05f20bbc7..97faf8933 100644 --- a/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs @@ -2,7 +2,6 @@ // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // - namespace ImageProcessorCore.Processors { using System.Numerics; @@ -35,16 +34,18 @@ namespace ImageProcessorCore.Processors /// protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) { - processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle); + this.processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle); if (this.Expand) { - CreateNewTarget(target, sourceRectangle, processMatrix); + CreateNewTarget(target, sourceRectangle, this.processMatrix); } } /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { + int height = target.Height; + int width = target.Width; Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); using (IPixelAccessor sourcePixels = source.Lock()) @@ -52,11 +53,11 @@ namespace ImageProcessorCore.Processors { Parallel.For( 0, - target.Height, + height, this.ParallelOptions, y => { - for (int x = 0; x < target.Width; x++) + for (int x = 0; x < width; x++) { Point transformedPoint = Point.Rotate(new Point(x, y), matrix); if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) @@ -65,7 +66,7 @@ namespace ImageProcessorCore.Processors } } - OnRowProcessed(); + this.OnRowProcessed(); }); } } diff --git a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 5981be9e2..24285d67b 100644 --- a/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -50,6 +50,8 @@ namespace ImageProcessorCore.Processors /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { + int height = target.Height; + int width = target.Width; Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix); using (IPixelAccessor sourcePixels = source.Lock()) @@ -57,11 +59,11 @@ namespace ImageProcessorCore.Processors { Parallel.For( 0, - target.Height, + height, this.ParallelOptions, y => { - for (int x = 0; x < target.Width; x++) + for (int x = 0; x < width; x++) { Point transformedPoint = Point.Skew(new Point(x, y), matrix); if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y))