Browse Source

Merge branch 'master' into tiff-format

pull/1570/head
James Jackson-South 5 years ago
committed by GitHub
parent
commit
6a8806f6f4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      shared-infrastructure
  2. 10
      src/ImageSharp/Processing/BinaryThresholdMode.cs
  3. 32
      src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs
  4. 77
      src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs
  5. 2
      src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs
  6. 22
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  7. 16
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
  8. 40
      tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs
  9. 110
      tests/ImageSharp.Tests/Processing/IntegralImageTests.cs
  10. 8
      tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs

2
shared-infrastructure

@ -1 +1 @@
Subproject commit bc88dab1746d34048d938566a313848a7a911869
Subproject commit 06a733983486638b9e38197c7c6eb197ecac43e6

10
src/ImageSharp/Processing/BinaryThresholdColorComponent.cs → src/ImageSharp/Processing/BinaryThresholdMode.cs

@ -4,22 +4,22 @@
namespace SixLabors.ImageSharp.Processing
{
/// <summary>
/// The color component to be compared to threshold.
/// Selects the value to be compared to threshold.
/// </summary>
public enum BinaryThresholdColorComponent : int
public enum BinaryThresholdMode
{
/// <summary>
/// Luminance color component according to ITU-R Recommendation BT.709.
/// Compare the color luminance (according to ITU-R Recommendation BT.709).
/// </summary>
Luminance = 0,
/// <summary>
/// HSL saturation color component.
/// Compare the HSL saturation of the color.
/// </summary>
Saturation = 1,
/// <summary>
/// Maximum of YCbCr chroma value, i.e. Cb and Cr distance from achromatic value.
/// Compare the maximum of YCbCr chroma value, i.e. Cb and Cr distance from achromatic value.
/// </summary>
MaxChroma = 2,
}

32
src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs

@ -19,20 +19,20 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="threshold">The threshold to apply binarization of the image. Must be between 0 and 1.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdColorComponent.Luminance));
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance));
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="threshold">The threshold to apply binarization of the image. Must be between 0 and 1.</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
/// <param name="mode">Selects the value to be compared to threshold.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
BinaryThresholdColorComponent colorComponent)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, colorComponent));
BinaryThresholdMode mode)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, mode));
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
@ -48,14 +48,14 @@ namespace SixLabors.ImageSharp.Processing
this IImageProcessingContext source,
float threshold,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdColorComponent.Luminance), rectangle);
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance), rectangle);
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="threshold">The threshold to apply binarization of the image. Must be between 0 and 1.</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
/// <param name="mode">Selects the value to be compared to threshold.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
@ -63,9 +63,9 @@ namespace SixLabors.ImageSharp.Processing
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
BinaryThresholdColorComponent colorComponent,
BinaryThresholdMode mode,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, colorComponent), rectangle);
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, mode), rectangle);
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing
float threshold,
Color upperColor,
Color lowerColor)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance));
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance));
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
@ -90,15 +90,15 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="threshold">The threshold to apply binarization of the image. Must be between 0 and 1.</param>
/// <param name="upperColor">The color to use for pixels that are above the threshold.</param>
/// <param name="lowerColor">The color to use for pixels that are below the threshold</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
/// <param name="mode">Selects the value to be compared to threshold.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
Color upperColor,
Color lowerColor,
BinaryThresholdColorComponent colorComponent)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, colorComponent));
BinaryThresholdMode mode)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, mode));
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
@ -118,7 +118,7 @@ namespace SixLabors.ImageSharp.Processing
Color upperColor,
Color lowerColor,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance), rectangle);
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance), rectangle);
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="threshold">The threshold to apply binarization of the image. Must be between 0 and 1.</param>
/// <param name="upperColor">The color to use for pixels that are above the threshold.</param>
/// <param name="lowerColor">The color to use for pixels that are below the threshold</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
/// <param name="mode">Selects the value to be compared to threshold.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
@ -137,8 +137,8 @@ namespace SixLabors.ImageSharp.Processing
float threshold,
Color upperColor,
Color lowerColor,
BinaryThresholdColorComponent colorComponent,
BinaryThresholdMode mode,
Rectangle rectangle) =>
source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, colorComponent), rectangle);
source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, mode), rectangle);
}
}

77
src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs

@ -0,0 +1,77 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing
{
/// <summary>
/// Defines extensions that allow the computation of image integrals on an <see cref="Image"/>
/// </summary>
public static partial class ProcessingExtensions
{
/// <summary>
/// Apply an image integral. <See href="https://en.wikipedia.org/wiki/Summed-area_table"/>
/// </summary>
/// <param name="source">The image on which to apply the integral.</param>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <returns>The <see cref="Buffer2D{T}"/> containing all the sums.</returns>
public static Buffer2D<ulong> CalculateIntegralImage<TPixel>(this Image<TPixel> source)
where TPixel : unmanaged, IPixel<TPixel>
{
Configuration configuration = source.GetConfiguration();
int endY = source.Height;
int endX = source.Width;
Buffer2D<ulong> intImage = configuration.MemoryAllocator.Allocate2D<ulong>(source.Width, source.Height);
ulong sumX0 = 0;
using (IMemoryOwner<L8> tempRow = configuration.MemoryAllocator.Allocate<L8>(source.Width))
{
Span<L8> tempSpan = tempRow.GetSpan();
Span<TPixel> sourceRow = source.GetPixelRowSpan(0);
Span<ulong> destRow = intImage.GetRowSpan(0);
PixelOperations<TPixel>.Instance.ToL8(configuration, sourceRow, tempSpan);
// First row
for (int x = 0; x < endX; x++)
{
sumX0 += tempSpan[x].PackedValue;
destRow[x] = sumX0;
}
Span<ulong> previousDestRow = destRow;
// All other rows
for (int y = 1; y < endY; y++)
{
sourceRow = source.GetPixelRowSpan(y);
destRow = intImage.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToL8(configuration, sourceRow, tempSpan);
// Process first column
sumX0 = tempSpan[0].PackedValue;
destRow[0] = sumX0 + previousDestRow[0];
// Process all other colmns
for (int x = 1; x < endX; x++)
{
sumX0 += tempSpan[x].PackedValue;
destRow[x] = sumX0 + previousDestRow[x];
}
previousDestRow = destRow;
}
}
return intImage;
}
}
}

2
src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Adds extensions that allow the processing of images to the <see cref="Image{TPixel}"/> type.
/// </summary>
public static class ProcessingExtensions
public static partial class ProcessingExtensions
{
/// <summary>
/// Mutates the source image by applying the image operation to it.

22
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// Initializes a new instance of the <see cref="BinaryThresholdProcessor"/> class.
/// </summary>
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
public BinaryThresholdProcessor(float threshold, BinaryThresholdColorComponent colorComponent)
: this(threshold, Color.White, Color.Black, colorComponent)
/// <param name="mode">The color component to be compared to threshold.</param>
public BinaryThresholdProcessor(float threshold, BinaryThresholdMode mode)
: this(threshold, Color.White, Color.Black, mode)
{
}
@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// </summary>
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
public BinaryThresholdProcessor(float threshold)
: this(threshold, Color.White, Color.Black, BinaryThresholdColorComponent.Luminance)
: this(threshold, Color.White, Color.Black, BinaryThresholdMode.Luminance)
{
}
@ -36,14 +36,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
/// <param name="upperColor">The color to use for pixels that are above the threshold.</param>
/// <param name="lowerColor">The color to use for pixels that are below the threshold.</param>
/// <param name="colorComponent">The color component to be compared to threshold.</param>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor, BinaryThresholdColorComponent colorComponent)
/// <param name="mode">The color component to be compared to threshold.</param>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor, BinaryThresholdMode mode)
{
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold));
this.Threshold = threshold;
this.UpperColor = upperColor;
this.LowerColor = lowerColor;
this.ColorComponent = colorComponent;
this.Mode = mode;
}
/// <summary>
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// <param name="upperColor">The color to use for pixels that are above the threshold.</param>
/// <param name="lowerColor">The color to use for pixels that are below the threshold.</param>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor)
: this(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance)
: this(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance)
{
}
@ -73,10 +73,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// </summary>
public Color LowerColor { get; }
/// <summary>
/// Gets a value indicating whether to use saturation value instead of luminance.
/// <summary>
/// Gets the <see cref="BinaryThresholdMode"/> defining the value to be compared to threshold.
/// </summary>
public BinaryThresholdColorComponent ColorComponent { get; }
public BinaryThresholdMode Mode { get; }
/// <inheritdoc />
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle)

16
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
upper,
lower,
threshold,
this.definition.ColorComponent,
this.definition.Mode,
configuration);
ParallelRowIterator.IterateRows<RowOperation, Rgb24>(
@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
private readonly TPixel upper;
private readonly TPixel lower;
private readonly byte threshold;
private readonly BinaryThresholdColorComponent colorComponent;
private readonly BinaryThresholdMode mode;
private readonly int startX;
private readonly Configuration configuration;
@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
TPixel upper,
TPixel lower,
byte threshold,
BinaryThresholdColorComponent colorComponent,
BinaryThresholdMode mode,
Configuration configuration)
{
this.startX = startX;
@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
this.upper = upper;
this.lower = lower;
this.threshold = threshold;
this.colorComponent = colorComponent;
this.mode = mode;
this.configuration = configuration;
}
@ -96,9 +96,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
PixelOperations<TPixel>.Instance.ToRgb24(this.configuration, rowSpan, span);
switch (this.colorComponent)
switch (this.mode)
{
case BinaryThresholdColorComponent.Luminance:
case BinaryThresholdMode.Luminance:
{
byte threshold = this.threshold;
for (int x = 0; x < rowSpan.Length; x++)
@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
break;
}
case BinaryThresholdColorComponent.Saturation:
case BinaryThresholdMode.Saturation:
{
float threshold = this.threshold / 255F;
for (int x = 0; x < rowSpan.Length; x++)
@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
break;
}
case BinaryThresholdColorComponent.MaxChroma:
case BinaryThresholdMode.MaxChroma:
{
float threshold = this.threshold / 2F;
for (int x = 0; x < rowSpan.Length; x++)

40
tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs

@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
this.operations.BinaryThreshold(.23f);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Luminance, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Luminance, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
this.operations.BinaryThreshold(.93f, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Luminance, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Luminance, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Luminance, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Luminance, p.Mode);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
}
@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
{
this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(BinaryThresholdColorComponent.Luminance, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Luminance, p.Mode);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
@ -57,10 +57,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinarySaturationThreshold_CorrectProcessor()
{
this.operations.BinaryThreshold(.23f, BinaryThresholdColorComponent.Saturation);
this.operations.BinaryThreshold(.23f, BinaryThresholdMode.Saturation);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Saturation, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Saturation, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -68,10 +68,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinarySaturationThreshold_rect_CorrectProcessor()
{
this.operations.BinaryThreshold(.93f, BinaryThresholdColorComponent.Saturation, this.rect);
this.operations.BinaryThreshold(.93f, BinaryThresholdMode.Saturation, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Saturation, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Saturation, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -79,10 +79,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinarySaturationThreshold_CorrectProcessorWithUpperLower()
{
this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdColorComponent.Saturation);
this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdMode.Saturation);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Saturation, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Saturation, p.Mode);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
}
@ -90,10 +90,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinarySaturationThreshold_rect_CorrectProcessorWithUpperLower()
{
this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdColorComponent.Saturation, this.rect);
this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdMode.Saturation, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.Saturation, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.Saturation, p.Mode);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
}
@ -101,10 +101,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinaryMaxChromaThreshold_CorrectProcessor()
{
this.operations.BinaryThreshold(.23f, BinaryThresholdColorComponent.MaxChroma);
this.operations.BinaryThreshold(.23f, BinaryThresholdMode.MaxChroma);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.MaxChroma, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -112,10 +112,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinaryMaxChromaThreshold_rect_CorrectProcessor()
{
this.operations.BinaryThreshold(.93f, BinaryThresholdColorComponent.MaxChroma, this.rect);
this.operations.BinaryThreshold(.93f, BinaryThresholdMode.MaxChroma, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.MaxChroma, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode);
Assert.Equal(Color.White, p.UpperColor);
Assert.Equal(Color.Black, p.LowerColor);
}
@ -123,10 +123,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinaryMaxChromaThreshold_CorrectProcessorWithUpperLower()
{
this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdColorComponent.MaxChroma);
this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdMode.MaxChroma);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>();
Assert.Equal(.23f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.MaxChroma, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
}
@ -134,10 +134,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
[Fact]
public void BinaryMaxChromaThreshold_rect_CorrectProcessorWithUpperLower()
{
this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdColorComponent.MaxChroma, this.rect);
this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdMode.MaxChroma, this.rect);
BinaryThresholdProcessor p = this.Verify<BinaryThresholdProcessor>(this.rect);
Assert.Equal(.93f, p.Threshold);
Assert.Equal(BinaryThresholdColorComponent.MaxChroma, p.ColorComponent);
Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode);
Assert.Equal(Color.HotPink, p.UpperColor);
Assert.Equal(Color.Yellow, p.LowerColor);
}

110
tests/ImageSharp.Tests/Processing/IntegralImageTests.cs

@ -0,0 +1,110 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Transforms
{
public class IntegralImageTests : BaseImageOperationsExtensionTest
{
[Theory]
[WithFile(TestImages.Png.Bradley01, PixelTypes.Rgba32)]
[WithFile(TestImages.Png.Bradley02, PixelTypes.Rgba32)]
[WithFile(TestImages.Png.Ducky, PixelTypes.Rgba32)]
public void CalculateIntegralImage_Rgba32Works(TestImageProvider<Rgba32> provider)
{
using Image<Rgba32> image = provider.GetImage();
// Act:
Buffer2D<ulong> integralBuffer = image.CalculateIntegralImage();
// Assert:
VerifySumValues(provider, integralBuffer, (Rgba32 pixel) =>
{
L8 outputPixel = default;
outputPixel.FromRgba32(pixel);
return outputPixel.PackedValue;
});
}
[Theory]
[WithFile(TestImages.Png.Bradley01, PixelTypes.L8)]
[WithFile(TestImages.Png.Bradley02, PixelTypes.L8)]
public void CalculateIntegralImage_L8Works(TestImageProvider<L8> provider)
{
using Image<L8> image = provider.GetImage();
// Act:
Buffer2D<ulong> integralBuffer = image.CalculateIntegralImage();
// Assert:
VerifySumValues(provider, integralBuffer, (L8 pixel) => { return pixel.PackedValue; });
}
private static void VerifySumValues<TPixel>(
TestImageProvider<TPixel> provider,
Buffer2D<ulong> integralBuffer,
System.Func<TPixel, ulong> getPixel)
where TPixel : unmanaged, IPixel<TPixel>
{
Image<TPixel> image = provider.GetImage();
// Check top-left corner
Assert.Equal(getPixel(image[0, 0]), integralBuffer[0, 0]);
ulong pixelValues = 0;
pixelValues += getPixel(image[0, 0]);
pixelValues += getPixel(image[1, 0]);
pixelValues += getPixel(image[0, 1]);
pixelValues += getPixel(image[1, 1]);
// Check top-left 2x2 pixels
Assert.Equal(pixelValues, integralBuffer[1, 1]);
pixelValues = 0;
pixelValues += getPixel(image[image.Width - 3, 0]);
pixelValues += getPixel(image[image.Width - 2, 0]);
pixelValues += getPixel(image[image.Width - 1, 0]);
pixelValues += getPixel(image[image.Width - 3, 1]);
pixelValues += getPixel(image[image.Width - 2, 1]);
pixelValues += getPixel(image[image.Width - 1, 1]);
// Check top-right 3x2 pixels
Assert.Equal(pixelValues, integralBuffer[image.Width - 1, 1] + 0 - 0 - integralBuffer[image.Width - 4, 1]);
pixelValues = 0;
pixelValues += getPixel(image[0, image.Height - 3]);
pixelValues += getPixel(image[0, image.Height - 2]);
pixelValues += getPixel(image[0, image.Height - 1]);
pixelValues += getPixel(image[1, image.Height - 3]);
pixelValues += getPixel(image[1, image.Height - 2]);
pixelValues += getPixel(image[1, image.Height - 1]);
// Check bottom-left 2x3 pixels
Assert.Equal(pixelValues, integralBuffer[1, image.Height - 1] + 0 - integralBuffer[1, image.Height - 4] - 0);
pixelValues = 0;
pixelValues += getPixel(image[image.Width - 3, image.Height - 3]);
pixelValues += getPixel(image[image.Width - 2, image.Height - 3]);
pixelValues += getPixel(image[image.Width - 1, image.Height - 3]);
pixelValues += getPixel(image[image.Width - 3, image.Height - 2]);
pixelValues += getPixel(image[image.Width - 2, image.Height - 2]);
pixelValues += getPixel(image[image.Width - 1, image.Height - 2]);
pixelValues += getPixel(image[image.Width - 3, image.Height - 1]);
pixelValues += getPixel(image[image.Width - 2, image.Height - 1]);
pixelValues += getPixel(image[image.Width - 1, image.Height - 1]);
// Check bottom-right 3x3 pixels
Assert.Equal(pixelValues, integralBuffer[image.Width - 1, image.Height - 1] + integralBuffer[image.Width - 4, image.Height - 4] - integralBuffer[image.Width - 1, image.Height - 4] - integralBuffer[image.Width - 4, image.Height - 1]);
}
}
}

8
tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs

@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdColorComponent.Saturation));
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.Saturation));
image.DebugSave(provider, value);
image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo));
}
@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
{
var bounds = new Rectangle(image.Width / 8, image.Height / 8, 6 * image.Width / 8, 6 * image.Width / 8);
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdColorComponent.Saturation, bounds));
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.Saturation, bounds));
image.DebugSave(provider, value);
image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo));
}
@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdColorComponent.MaxChroma));
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.MaxChroma));
image.DebugSave(provider, value);
if (!TestEnvironment.Is64BitProcess && TestEnvironment.IsFramework)
@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
{
var bounds = new Rectangle(image.Width / 8, image.Height / 8, 6 * image.Width / 8, 6 * image.Width / 8);
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdColorComponent.MaxChroma, bounds));
image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.MaxChroma, bounds));
image.DebugSave(provider, value);
if (!TestEnvironment.Is64BitProcess && TestEnvironment.IsFramework)

Loading…
Cancel
Save