Browse Source

Sampler performance optimizations

Former-commit-id: 57f9665225227b25a9dc53357985097001df37c8
Former-commit-id: 0ba692a70a1480b5de88015bb0660a2471f63ec3
Former-commit-id: 055257264bc4063a23db7c056a7cfa7a7c4394be
pull/1/head
James Jackson-South 10 years ago
parent
commit
cbf476e34e
  1. 16
      src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs
  2. 8
      src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs
  3. 16
      src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs
  4. 13
      src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs
  5. 6
      src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs

16
src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs

@ -24,7 +24,7 @@ namespace ImageProcessorCore.Processors
private Rectangle cropRectangle;
/// <summary>
/// Initializes a new instance of the <see cref="EntropyCropProcessor"/> class.
/// Initializes a new instance of the <see cref="EntropyCropProcessor{T,TP}"/> class.
/// </summary>
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
/// <exception cref="ArgumentException">
@ -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<T, TP> sourcePixels = source.Lock())
using (IPixelAccessor<T, TP> 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();

8
src/ImageProcessorCore/Samplers/Processors/Matrix3x2Processor.cs

@ -19,8 +19,6 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Creates a new target to contain the results of the matrix transform.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="sourceRectangle">The source rectangle.</param>
/// <param name="processMatrix">The processing matrix.</param>
@ -37,8 +35,6 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Gets a transform matrix adjusted to center upon the target image bounds.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image.</param>
/// <param name="matrix">The transform matrix.</param>
@ -47,8 +43,8 @@ namespace ImageProcessorCore.Processors
/// </returns>
protected static Matrix3x2 GetCenteredMatrix(ImageBase<T, TP> target, ImageBase<T, TP> 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;
}
}

16
src/ImageProcessorCore/Samplers/Processors/RotateFlipProcessor.cs

@ -18,7 +18,7 @@ namespace ImageProcessorCore.Processors
where TP : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="RotateFlipProcessor"/> class.
/// Initializes a new instance of the <see cref="RotateFlipProcessor{T,TP}"/> class.
/// </summary>
/// <param name="rotateType">The <see cref="RotateType"/> used to perform rotation.</param>
/// <param name="flipType">The <see cref="FlipType"/> used to perform flipping.</param>
@ -72,8 +72,6 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Rotates the image 270 degrees clockwise at the centre point.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate270(ImageBase<T, TP> target, ImageBase<T, TP> source)
@ -110,8 +108,6 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Rotates the image 180 degrees clockwise at the centre point.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate180(ImageBase<T, TP> target, ImageBase<T, TP> source)
@ -143,8 +139,6 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Rotates the image 90 degrees clockwise at the centre point.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate90(ImageBase<T, TP> target, ImageBase<T, TP> 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.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">Target image to apply the process to.</param>
private void FlipX(ImageBase<T, TP> 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<T, TP> temp = new Image<T, TP>(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.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="target">Target image to apply the process to.</param>
private void FlipY(ImageBase<T, TP> target)
{
int width = target.Width;
int height = target.Height;
int halfWidth = (int)Math.Ceiling(width / 2d);
int halfWidth = (int)Math.Ceiling(width * .5F);
Image<T, TP> temp = new Image<T, TP>(width, height);
temp.ClonePixels(width, height, target.Pixels);

13
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.
// </copyright>
namespace ImageProcessorCore.Processors
{
using System.Numerics;
@ -35,16 +34,18 @@ namespace ImageProcessorCore.Processors
/// <inheritdoc/>
protected override void OnApply(ImageBase<T, TP> target, ImageBase<T, TP> 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);
}
}
/// <inheritdoc/>
protected override void Apply(ImageBase<T, TP> target, ImageBase<T, TP> 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<T, TP> 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();
});
}
}

6
src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs

@ -50,6 +50,8 @@ namespace ImageProcessorCore.Processors
/// <inheritdoc/>
protected override void Apply(ImageBase<T, TP> target, ImageBase<T, TP> 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<T, TP> 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))

Loading…
Cancel
Save