mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 180 additions and 141 deletions
@ -1,50 +1,46 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.ImageSharp.Processing.Processors.Convolution; |
using SixLabors.ImageSharp.Processing.Processors.Convolution; |
||||
using SixLabors.Primitives; |
using SixLabors.Primitives; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing |
namespace SixLabors.ImageSharp.Processing |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Adds Gaussian sharpening extensions to the <see cref="Image{TPixel}"/> type.
|
/// Adds Gaussian sharpening extensions to the <see cref="Image"/> type.
|
||||
/// </summary>
|
/// </summary>
|
||||
public static class GaussianSharpenExtensions |
public static class GaussianSharpenExtensions |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Applies a Gaussian sharpening filter to the image.
|
/// Applies a Gaussian sharpening filter to the image.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
/// <param name="source">The image this method extends.</param>
|
/// <param name="source">The image this method extends.</param>
|
||||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
public static IImageProcessingContext<TPixel> GaussianSharpen<TPixel>(this IImageProcessingContext<TPixel> source) |
public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) => |
||||
where TPixel : struct, IPixel<TPixel> |
source.ApplyProcessor(new GaussianSharpenProcessor()); |
||||
=> source.ApplyProcessor(new GaussianSharpenProcessor<TPixel>()); |
|
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Applies a Gaussian sharpening filter to the image.
|
/// Applies a Gaussian sharpening filter to the image.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
/// <param name="source">The image this method extends.</param>
|
/// <param name="source">The image this method extends.</param>
|
||||
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
|
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
|
||||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
public static IImageProcessingContext<TPixel> GaussianSharpen<TPixel>(this IImageProcessingContext<TPixel> source, float sigma) |
public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) => |
||||
where TPixel : struct, IPixel<TPixel> |
source.ApplyProcessor(new GaussianSharpenProcessor(sigma)); |
||||
=> source.ApplyProcessor(new GaussianSharpenProcessor<TPixel>(sigma)); |
|
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Applies a Gaussian sharpening filter to the image.
|
/// Applies a Gaussian sharpening filter to the image.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
/// <param name="source">The image this method extends.</param>
|
/// <param name="source">The image this method extends.</param>
|
||||
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
|
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
|
||||
/// <param name="rectangle">
|
/// <param name="rectangle">
|
||||
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
/// </param>
|
/// </param>
|
||||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
public static IImageProcessingContext<TPixel> GaussianSharpen<TPixel>(this IImageProcessingContext<TPixel> source, float sigma, Rectangle rectangle) |
public static IImageProcessingContext GaussianSharpen( |
||||
where TPixel : struct, IPixel<TPixel> |
this IImageProcessingContext source, |
||||
=> source.ApplyProcessor(new GaussianSharpenProcessor<TPixel>(sigma), rectangle); |
float sigma, |
||||
|
Rectangle rectangle) => |
||||
|
source.ApplyProcessor(new GaussianSharpenProcessor(sigma), rectangle); |
||||
} |
} |
||||
} |
} |
||||
@ -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 |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Kernel radius is calculated using the minimum viable value.
|
||||
|
/// <see cref="http://chemaguerra.com/gaussian-filter-radius/"/>.
|
||||
|
/// </summary>
|
||||
|
internal static int GetDefaultGaussianRadius(float sigma) |
||||
|
{ |
||||
|
return (int)MathF.Ceiling(sigma * 3); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
|
||||
|
/// </summary>
|
||||
|
/// <returns>The <see cref="DenseMatrix{T}"/>.</returns>
|
||||
|
internal static DenseMatrix<float> CreateGaussianBlurKernel(int size, float weight) |
||||
|
{ |
||||
|
var kernel = new DenseMatrix<float>(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; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
|
||||
|
/// </summary>
|
||||
|
/// <returns>The <see cref="DenseMatrix{T}"/>.</returns>
|
||||
|
internal static DenseMatrix<float> CreateGaussianSharpenKernel(int size, float weight) |
||||
|
{ |
||||
|
var kernel = new DenseMatrix<float>(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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies Gaussian sharpening processing to the image.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class GaussianSharpenProcessor<TPixel> : ImageProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="GaussianSharpenProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="definition">The <see cref="GaussianBlurProcessor"/> defining the processor parameters.</param>
|
||||
|
public GaussianSharpenProcessor(GaussianSharpenProcessor definition) |
||||
|
{ |
||||
|
int kernelSize = (definition.Radius * 2) + 1; |
||||
|
this.KernelX = ConvolutionProcessorHelpers.CreateGaussianSharpenKernel(kernelSize, definition.Sigma); |
||||
|
this.KernelY = this.KernelX.Transpose(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public DenseMatrix<float> KernelX { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public DenseMatrix<float> KernelY { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
||||
|
=> new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue