diff --git a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs
index 675bbc142d..64aa7b5db3 100644
--- a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs
+++ b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs
@@ -1,50 +1,46 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Convolution;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing
{
///
- /// Adds Gaussian sharpening extensions to the type.
+ /// Adds Gaussian sharpening extensions to the type.
///
public static class GaussianSharpenExtensions
{
///
/// Applies a Gaussian sharpening filter to the image.
///
- /// The pixel format.
/// The image this method extends.
/// The .
- public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source)
- where TPixel : struct, IPixel
- => source.ApplyProcessor(new GaussianSharpenProcessor());
+ public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) =>
+ source.ApplyProcessor(new GaussianSharpenProcessor());
///
/// Applies a Gaussian sharpening filter to the image.
///
- /// The pixel format.
/// The image this method extends.
/// The 'sigma' value representing the weight of the blur.
/// The .
- public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma)
- where TPixel : struct, IPixel
- => source.ApplyProcessor(new GaussianSharpenProcessor(sigma));
+ public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) =>
+ source.ApplyProcessor(new GaussianSharpenProcessor(sigma));
///
/// Applies a Gaussian sharpening filter to the image.
///
- /// The pixel format.
/// The image this method extends.
/// The 'sigma' value representing the weight of the blur.
///
/// The structure that specifies the portion of the image object to alter.
///
/// The .
- public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma, Rectangle rectangle)
- where TPixel : struct, IPixel
- => source.ApplyProcessor(new GaussianSharpenProcessor(sigma), rectangle);
+ public static IImageProcessingContext GaussianSharpen(
+ this IImageProcessingContext source,
+ float sigma,
+ Rectangle rectangle) =>
+ source.ApplyProcessor(new GaussianSharpenProcessor(sigma), rectangle);
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs
new file mode 100644
index 0000000000..bb0072b82e
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs
@@ -0,0 +1,93 @@
+// // Copyright (c) Six Labors and contributors.
+// // Licensed under the Apache License, Version 2.0.
+
+using System;
+
+using SixLabors.ImageSharp.Primitives;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ internal static class ConvolutionProcessorHelpers
+ {
+ ///
+ /// Kernel radius is calculated using the minimum viable value.
+ /// .
+ ///
+ internal static int GetDefaultGaussianRadius(float sigma)
+ {
+ return (int)MathF.Ceiling(sigma * 3);
+ }
+
+ ///
+ /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
+ ///
+ /// The .
+ internal static DenseMatrix CreateGaussianBlurKernel(int size, float weight)
+ {
+ var kernel = new DenseMatrix(size, 1);
+
+ float sum = 0F;
+ float midpoint = (size - 1) / 2F;
+
+ for (int i = 0; i < size; i++)
+ {
+ float x = i - midpoint;
+ float gx = ImageMaths.Gaussian(x, weight);
+ sum += gx;
+ kernel[0, i] = gx;
+ }
+
+ // Normalize kernel so that the sum of all weights equals 1
+ for (int i = 0; i < size; i++)
+ {
+ kernel[0, i] /= sum;
+ }
+
+ return kernel;
+ }
+
+ ///
+ /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
+ ///
+ /// The .
+ internal static DenseMatrix CreateGaussianSharpenKernel(int size, float weight)
+ {
+ var kernel = new DenseMatrix(size, 1);
+
+ float sum = 0;
+
+ float midpoint = (size - 1) / 2F;
+ for (int i = 0; i < size; i++)
+ {
+ float x = i - midpoint;
+ float gx = ImageMaths.Gaussian(x, weight);
+ sum += gx;
+ kernel[0, i] = gx;
+ }
+
+ // Invert the kernel for sharpening.
+ int midpointRounded = (int)midpoint;
+ for (int i = 0; i < size; i++)
+ {
+ if (i == midpointRounded)
+ {
+ // Calculate central value
+ kernel[0, i] = (2F * sum) - kernel[0, i];
+ }
+ else
+ {
+ // invert value
+ kernel[0, i] = -kernel[0, i];
+ }
+ }
+
+ // Normalize kernel so that the sum of all weights equals 1
+ for (int i = 0; i < size; i++)
+ {
+ kernel[0, i] /= sum;
+ }
+
+ return kernel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
index 33e2ef955d..c64a024f9f 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
@@ -1,14 +1,13 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
- /// Defines a gaussian blur processor with a (Sigma, Radius) pair.
+ /// Defines Gaussian blur by a (Sigma, Radius) pair.
///
public class GaussianBlurProcessor : IImageProcessor
{
@@ -21,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// Initializes a new instance of the class.
///
public GaussianBlurProcessor()
- : this(DefaultSigma, CalculateDefaultRadius(DefaultSigma))
+ : this(DefaultSigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(DefaultSigma))
{
}
@@ -30,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// The 'sigma' value representing the weight of the blur.
public GaussianBlurProcessor(float sigma)
- : this(sigma, CalculateDefaultRadius(sigma))
+ : this(sigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(sigma))
{
}
@@ -77,14 +76,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
return new GaussianBlurProcessor(this);
}
-
- ///
- /// Kernel radius is calculated using the minimum viable value.
- /// .
- ///
- private static int CalculateDefaultRadius(float sigma)
- {
- return (int)MathF.Ceiling(sigma * 3);
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs
index 9b60fb2d2e..a129ff5473 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs
@@ -1,5 +1,5 @@
-// // Copyright (c) Six Labors and contributors.
-// // Licensed under the Apache License, Version 2.0.
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
@@ -14,17 +14,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
internal class GaussianBlurProcessor : ImageProcessor
where TPixel : struct, IPixel
{
- private readonly GaussianBlurProcessor definition;
-
///
/// Initializes a new instance of the class.
///
/// The defining the processor parameters.
public GaussianBlurProcessor(GaussianBlurProcessor definition)
{
- this.definition = definition;
int kernelSize = (definition.Radius * 2) + 1;
- this.KernelX = CreateGaussianKernel(kernelSize, definition.Sigma);
+ this.KernelX = ConvolutionProcessorHelpers.CreateGaussianBlurKernel(kernelSize, definition.Sigma);
this.KernelY = this.KernelX.Transpose();
}
@@ -47,33 +44,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
source,
sourceRectangle,
configuration);
-
- ///
- /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
- ///
- /// The
- private static DenseMatrix CreateGaussianKernel(int size, float weight)
- {
- var kernel = new DenseMatrix(size, 1);
-
- float sum = 0F;
- float midpoint = (size - 1) / 2F;
-
- for (int i = 0; i < size; i++)
- {
- float x = i - midpoint;
- float gx = ImageMaths.Gaussian(x, weight);
- sum += gx;
- kernel[0, i] = gx;
- }
-
- // Normalize kernel so that the sum of all weights equals 1
- for (int i = 0; i < size; i++)
- {
- kernel[0, i] /= sum;
- }
-
- return kernel;
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs
index 001471720a..bc06ee6182 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs
@@ -3,38 +3,38 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Primitives;
-using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
- /// Applies Gaussian sharpening processing to the image.
+ /// Defines Gaussian sharpening by a (Sigma, Radius) pair.
///
- /// The pixel format.
- internal class GaussianSharpenProcessor : ImageProcessor
- where TPixel : struct, IPixel
+ public class GaussianSharpenProcessor : IImageProcessor
{
+ ///
+ /// The default value for .
+ ///
+ public const float DefaultSigma = 3f;
+
///
- /// The maximum size of the kernel in either direction.
+ /// Initializes a new instance of the class.
///
- private readonly int kernelSize;
+ public GaussianSharpenProcessor()
+ : this(DefaultSigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(DefaultSigma))
+ {
+ }
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- ///
- /// The 'sigma' value representing the weight of the sharpening.
- ///
- public GaussianSharpenProcessor(float sigma = 3F)
- : this(sigma, (int)MathF.Ceiling(sigma * 3))
+ /// The 'sigma' value representing the weight of the blur.
+ public GaussianSharpenProcessor(float sigma)
+ : this(sigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(sigma))
{
- // Kernel radius is calculated using the minimum viable value.
- // http://chemaguerra.com/gaussian-filter-radius/
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'radius' value representing the size of the area to sample.
@@ -45,10 +45,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
- /// The 'sigma' value representing the weight of the sharpen.
+ /// The 'sigma' value representing the weight of the blur.
///
///
/// The 'radius' value representing the size of the area to sample.
@@ -56,10 +56,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
public GaussianSharpenProcessor(float sigma, int radius)
{
- this.kernelSize = (radius * 2) + 1;
this.Sigma = sigma;
- this.KernelX = this.CreateGaussianKernel();
- this.KernelY = this.KernelX.Transpose();
+ this.Radius = radius;
}
///
@@ -68,63 +66,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public float Sigma { get; }
///
- /// Gets the horizontal gradient operator.
- ///
- public DenseMatrix KernelX { get; }
-
- ///
- /// Gets the vertical gradient operator.
+ /// Gets the radius defining the size of the area to sample.
///
- public DenseMatrix KernelY { get; }
+ public int Radius { get; }
- ///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
- => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration);
-
- ///
- /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
- ///
- /// The
- private DenseMatrix CreateGaussianKernel()
+ public IImageProcessor CreatePixelSpecificProcessor()
+ where TPixel : struct, IPixel
{
- int size = this.kernelSize;
- float weight = this.Sigma;
- var kernel = new DenseMatrix(size, 1);
-
- float sum = 0;
-
- float midpoint = (size - 1) / 2F;
- for (int i = 0; i < size; i++)
- {
- float x = i - midpoint;
- float gx = ImageMaths.Gaussian(x, weight);
- sum += gx;
- kernel[0, i] = gx;
- }
-
- // Invert the kernel for sharpening.
- int midpointRounded = (int)midpoint;
- for (int i = 0; i < size; i++)
- {
- if (i == midpointRounded)
- {
- // Calculate central value
- kernel[0, i] = (2F * sum) - kernel[0, i];
- }
- else
- {
- // invert value
- kernel[0, i] = -kernel[0, i];
- }
- }
-
- // Normalize kernel so that the sum of all weights equals 1
- for (int i = 0; i < size; i++)
- {
- kernel[0, i] /= sum;
- }
-
- return kernel;
+ return new GaussianSharpenProcessor(this);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs
new file mode 100644
index 0000000000..edde9f9e7f
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Primitives;
+using SixLabors.Primitives;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Applies Gaussian sharpening processing to the image.
+ ///
+ /// The pixel format.
+ internal class GaussianSharpenProcessor : ImageProcessor
+ where TPixel : struct, IPixel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The defining the processor parameters.
+ public GaussianSharpenProcessor(GaussianSharpenProcessor definition)
+ {
+ int kernelSize = (definition.Radius * 2) + 1;
+ this.KernelX = ConvolutionProcessorHelpers.CreateGaussianSharpenKernel(kernelSize, definition.Sigma);
+ this.KernelY = this.KernelX.Transpose();
+ }
+
+ ///
+ /// Gets the horizontal gradient operator.
+ ///
+ public DenseMatrix KernelX { get; }
+
+ ///
+ /// Gets the vertical gradient operator.
+ ///
+ public DenseMatrix KernelY { get; }
+
+ ///
+ protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration);
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs
index 675498745e..7c2205f4e4 100644
--- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs
+++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
public void GaussianSharpen_GaussianSharpenProcessorDefaultsSet()
{
this.operations.GaussianSharpen();
- var processor = this.Verify>();
+ var processor = this.Verify();
Assert.Equal(3f, processor.Sigma);
}
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
public void GaussianSharpen_amount_GaussianSharpenProcessorDefaultsSet()
{
this.operations.GaussianSharpen(0.2f);
- var processor = this.Verify>();
+ var processor = this.Verify();
Assert.Equal(.2f, processor.Sigma);
}
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
public void GaussianSharpen_amount_rect_GaussianSharpenProcessorDefaultsSet()
{
this.operations.GaussianSharpen(0.6f, this.rect);
- var processor = this.Verify>(this.rect);
+ var processor = this.Verify(this.rect);
Assert.Equal(.6f, processor.Sigma);
}