From 2e09bb4a3c05b1c7d489391c0d373bd7dce83ee9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 17 Feb 2021 16:04:58 +0100 Subject: [PATCH 1/4] BinaryThresholdColorComponent -> BinaryThresholdMode --- ...lorComponent.cs => BinaryThresholdMode.cs} | 10 ++--- .../Binarization/BinaryThresholdExtensions.cs | 32 +++++++-------- .../Binarization/BinaryThresholdProcessor.cs | 22 +++++----- .../BinaryThresholdProcessor{TPixel}.cs | 16 ++++---- .../Binarization/BinaryThresholdTest.cs | 40 +++++++++---------- .../Binarization/BinaryThresholdTest.cs | 8 ++-- 6 files changed, 64 insertions(+), 64 deletions(-) rename src/ImageSharp/Processing/{BinaryThresholdColorComponent.cs => BinaryThresholdMode.cs} (53%) diff --git a/src/ImageSharp/Processing/BinaryThresholdColorComponent.cs b/src/ImageSharp/Processing/BinaryThresholdMode.cs similarity index 53% rename from src/ImageSharp/Processing/BinaryThresholdColorComponent.cs rename to src/ImageSharp/Processing/BinaryThresholdMode.cs index e46070dcb6..0ca1f08d14 100644 --- a/src/ImageSharp/Processing/BinaryThresholdColorComponent.cs +++ b/src/ImageSharp/Processing/BinaryThresholdMode.cs @@ -4,22 +4,22 @@ namespace SixLabors.ImageSharp.Processing { /// - /// The color component to be compared to threshold. + /// Selects the value to be compared to threshold. /// - public enum BinaryThresholdColorComponent : int + public enum BinaryThresholdMode { /// - /// Luminance color component according to ITU-R Recommendation BT.709. + /// Compare the color luminance (according to ITU-R Recommendation BT.709). /// Luminance = 0, /// - /// HSL saturation color component. + /// Compare the HSL saturation of the color. /// Saturation = 1, /// - /// 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. /// MaxChroma = 2, } diff --git a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs index 11c6433f22..5132fd731d 100644 --- a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs @@ -19,20 +19,20 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) - => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdColorComponent.Luminance)); + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance)); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The color component to be compared to threshold. + /// Selects the value to be compared to threshold. /// The to allow chaining of operations. 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)); /// /// 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); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The color component to be compared to threshold. + /// Selects the value to be compared to threshold. /// /// The structure that specifies the portion of the image object to alter. /// @@ -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); /// /// 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)); /// /// Applies binarization to the image splitting the pixels at the given threshold. @@ -90,15 +90,15 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The color component to be compared to threshold. + /// Selects the value to be compared to threshold. /// The to allow chaining of operations. 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)); /// /// 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); /// /// Applies binarization to the image splitting the pixels at the given threshold. @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The color component to be compared to threshold. + /// Selects the value to be compared to threshold. /// /// The structure that specifies the portion of the image object to alter. /// @@ -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); } } diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 24a3e6c1da..57356e541a 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. - /// The color component to be compared to threshold. - public BinaryThresholdProcessor(float threshold, BinaryThresholdColorComponent colorComponent) - : this(threshold, Color.White, Color.Black, colorComponent) + /// The color component to be compared to threshold. + public BinaryThresholdProcessor(float threshold, BinaryThresholdMode mode) + : this(threshold, Color.White, Color.Black, mode) { } @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// /// The threshold to split the image. Must be between 0 and 1. 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 /// The threshold to split the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. - /// The color component to be compared to threshold. - public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor, BinaryThresholdColorComponent colorComponent) + /// The color component to be compared to threshold. + 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; } /// @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. 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 /// public Color LowerColor { get; } - /// - /// Gets a value indicating whether to use saturation value instead of luminance. + /// + /// Gets a value indicating the value to be compared to threshold. /// - public BinaryThresholdColorComponent ColorComponent { get; } + public BinaryThresholdMode Mode { get; } /// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs index aa03cc27d2..5942c71641 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs +++ b/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( @@ -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 rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length); PixelOperations.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++) diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index a02ca36eeb..a2fb9f9bad 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/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(); 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(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(); 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(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(); 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(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(); 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(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(); 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(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(); 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(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); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs index 79ed4c7cdb..fd08eb2dea 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { using (Image 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 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) From 51769740ab74a647d5ac4edc874eeb31cfb47d9e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 17 Feb 2021 16:11:21 +0100 Subject: [PATCH 2/4] better docs --- .../Processors/Binarization/BinaryThresholdProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 57356e541a..77fc6938d9 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization public Color LowerColor { get; } /// - /// Gets a value indicating the value to be compared to threshold. + /// Gets the defining the value to be compared to threshold. /// public BinaryThresholdMode Mode { get; } From 33b118c8ce26e7ba3eb813a0f7bdfc26e6b12d5e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 18 Feb 2021 06:38:41 +0000 Subject: [PATCH 3/4] Update shared-infrastructure --- shared-infrastructure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-infrastructure b/shared-infrastructure index bc88dab174..06a7339834 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit bc88dab1746d34048d938566a313848a7a911869 +Subproject commit 06a733983486638b9e38197c7c6eb197ecac43e6 From 8147ec3bfc28c69f48a46b3803872c5c7dfdf0d7 Mon Sep 17 00:00:00 2001 From: David Rolland Date: Thu, 18 Feb 2021 21:28:26 +0900 Subject: [PATCH 4/4] Added image integral algorithm. --- .../ProcessingExtensions.IntegralImage.cs | 77 ++++++++++++ .../Extensions/ProcessingExtensions.cs | 2 +- .../Processing/IntegralImageTests.cs | 110 ++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs create mode 100644 tests/ImageSharp.Tests/Processing/IntegralImageTests.cs diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs new file mode 100644 index 0000000000..af6d32b216 --- /dev/null +++ b/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 +{ + /// + /// Defines extensions that allow the computation of image integrals on an + /// + public static partial class ProcessingExtensions + { + /// + /// Apply an image integral. + /// + /// The image on which to apply the integral. + /// The type of the pixel. + /// The containing all the sums. + public static Buffer2D CalculateIntegralImage(this Image source) + where TPixel : unmanaged, IPixel + { + Configuration configuration = source.GetConfiguration(); + + int endY = source.Height; + int endX = source.Width; + + Buffer2D intImage = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height); + ulong sumX0 = 0; + + using (IMemoryOwner tempRow = configuration.MemoryAllocator.Allocate(source.Width)) + { + Span tempSpan = tempRow.GetSpan(); + Span sourceRow = source.GetPixelRowSpan(0); + Span destRow = intImage.GetRowSpan(0); + + PixelOperations.Instance.ToL8(configuration, sourceRow, tempSpan); + + // First row + for (int x = 0; x < endX; x++) + { + sumX0 += tempSpan[x].PackedValue; + destRow[x] = sumX0; + } + + Span previousDestRow = destRow; + + // All other rows + for (int y = 1; y < endY; y++) + { + sourceRow = source.GetPixelRowSpan(y); + destRow = intImage.GetRowSpan(y); + + PixelOperations.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; + } + } +} diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index 0bf83812d0..ac14d84231 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Adds extensions that allow the processing of images to the type. /// - public static class ProcessingExtensions + public static partial class ProcessingExtensions { /// /// Mutates the source image by applying the image operation to it. diff --git a/tests/ImageSharp.Tests/Processing/IntegralImageTests.cs b/tests/ImageSharp.Tests/Processing/IntegralImageTests.cs new file mode 100644 index 0000000000..481463f47e --- /dev/null +++ b/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 provider) + { + using Image image = provider.GetImage(); + + // Act: + Buffer2D 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 provider) + { + using Image image = provider.GetImage(); + + // Act: + Buffer2D integralBuffer = image.CalculateIntegralImage(); + + // Assert: + VerifySumValues(provider, integralBuffer, (L8 pixel) => { return pixel.PackedValue; }); + } + + private static void VerifySumValues( + TestImageProvider provider, + Buffer2D integralBuffer, + System.Func getPixel) + where TPixel : unmanaged, IPixel + { + Image 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]); + } + } +}