|
|
@ -52,8 +52,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
using IMemoryOwner<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean); |
|
|
using IMemoryOwner<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean); |
|
|
|
|
|
|
|
|
// Build the histogram of the grayscale levels
|
|
|
// Build the histogram of the grayscale levels
|
|
|
var grayscaleOperation = new GrayscaleLevelsRowIntervalOperation(interest, histogramBuffer, source, this.LuminanceLevels); |
|
|
var grayscaleOperation = new GrayscaleLevelsRowOperation(interest, histogramBuffer, source, this.LuminanceLevels); |
|
|
ParallelRowIterator.IterateRowIntervals( |
|
|
ParallelRowIterator.IterateRows( |
|
|
this.Configuration, |
|
|
this.Configuration, |
|
|
interest, |
|
|
interest, |
|
|
in grayscaleOperation); |
|
|
in grayscaleOperation); |
|
|
@ -75,8 +75,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; |
|
|
float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; |
|
|
|
|
|
|
|
|
// Apply the cdf to each pixel of the image
|
|
|
// Apply the cdf to each pixel of the image
|
|
|
var cdfOperation = new CdfApplicationRowIntervalOperation(interest, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin); |
|
|
var cdfOperation = new CdfApplicationRowOperation(interest, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin); |
|
|
ParallelRowIterator.IterateRowIntervals( |
|
|
ParallelRowIterator.IterateRows( |
|
|
this.Configuration, |
|
|
this.Configuration, |
|
|
interest, |
|
|
interest, |
|
|
in cdfOperation); |
|
|
in cdfOperation); |
|
|
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// A <see langword="struct"/> implementing the grayscale levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
|
|
|
/// A <see langword="struct"/> implementing the grayscale levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
private readonly struct GrayscaleLevelsRowIntervalOperation : IRowIntervalOperation |
|
|
private readonly struct GrayscaleLevelsRowOperation : IRowOperation |
|
|
{ |
|
|
{ |
|
|
private readonly Rectangle bounds; |
|
|
private readonly Rectangle bounds; |
|
|
private readonly IMemoryOwner<int> histogramBuffer; |
|
|
private readonly IMemoryOwner<int> histogramBuffer; |
|
|
@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
private readonly int luminanceLevels; |
|
|
private readonly int luminanceLevels; |
|
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
public GrayscaleLevelsRowIntervalOperation( |
|
|
public GrayscaleLevelsRowOperation( |
|
|
Rectangle bounds, |
|
|
Rectangle bounds, |
|
|
IMemoryOwner<int> histogramBuffer, |
|
|
IMemoryOwner<int> histogramBuffer, |
|
|
ImageFrame<TPixel> source, |
|
|
ImageFrame<TPixel> source, |
|
|
@ -107,18 +107,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
/// <inheritdoc/>
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
public void Invoke(in RowInterval rows) |
|
|
public void Invoke(int y) |
|
|
{ |
|
|
{ |
|
|
ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan()); |
|
|
ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan()); |
|
|
for (int y = rows.Min; y < rows.Max; y++) |
|
|
ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); |
|
|
{ |
|
|
|
|
|
ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); |
|
|
|
|
|
|
|
|
|
|
|
for (int x = 0; x < this.bounds.Width; x++) |
|
|
for (int x = 0; x < this.bounds.Width; x++) |
|
|
{ |
|
|
{ |
|
|
int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels); |
|
|
int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels); |
|
|
Unsafe.Add(ref histogramBase, luminance)++; |
|
|
Unsafe.Add(ref histogramBase, luminance)++; |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -126,7 +123,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// A <see langword="struct"/> implementing the cdf application levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
|
|
|
/// A <see langword="struct"/> implementing the cdf application levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
private readonly struct CdfApplicationRowIntervalOperation : IRowIntervalOperation |
|
|
private readonly struct CdfApplicationRowOperation : IRowOperation |
|
|
{ |
|
|
{ |
|
|
private readonly Rectangle bounds; |
|
|
private readonly Rectangle bounds; |
|
|
private readonly IMemoryOwner<int> cdfBuffer; |
|
|
private readonly IMemoryOwner<int> cdfBuffer; |
|
|
@ -135,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
private readonly float numberOfPixelsMinusCdfMin; |
|
|
private readonly float numberOfPixelsMinusCdfMin; |
|
|
|
|
|
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
public CdfApplicationRowIntervalOperation( |
|
|
public CdfApplicationRowOperation( |
|
|
Rectangle bounds, |
|
|
Rectangle bounds, |
|
|
IMemoryOwner<int> cdfBuffer, |
|
|
IMemoryOwner<int> cdfBuffer, |
|
|
ImageFrame<TPixel> source, |
|
|
ImageFrame<TPixel> source, |
|
|
@ -151,20 +148,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization |
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
/// <inheritdoc/>
|
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
[MethodImpl(InliningOptions.ShortMethod)] |
|
|
public void Invoke(in RowInterval rows) |
|
|
public void Invoke(int y) |
|
|
{ |
|
|
{ |
|
|
ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan()); |
|
|
ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan()); |
|
|
for (int y = rows.Min; y < rows.Max; y++) |
|
|
ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); |
|
|
|
|
|
|
|
|
|
|
|
for (int x = 0; x < this.bounds.Width; x++) |
|
|
{ |
|
|
{ |
|
|
ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); |
|
|
ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); |
|
|
|
|
|
int luminance = GetLuminance(pixel, this.luminanceLevels); |
|
|
for (int x = 0; x < this.bounds.Width; x++) |
|
|
float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin; |
|
|
{ |
|
|
pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); |
|
|
ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); |
|
|
|
|
|
int luminance = GetLuminance(pixel, this.luminanceLevels); |
|
|
|
|
|
float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin; |
|
|
|
|
|
pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|