Skip to content

Commit

Permalink
Merge pull request #1555 from Franz1960/max-chroma-binarization
Browse files Browse the repository at this point in the history
New overloads for binary threshold operations. The new argument Color…
  • Loading branch information
JimBobSquarePants authored Feb 17, 2021
2 parents 2ae6018 + 045612f commit 6038be9
Show file tree
Hide file tree
Showing 36 changed files with 535 additions and 72 deletions.
35 changes: 25 additions & 10 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
# Set default behavior to:
# treat as text and
# normalize to Unix-style line endings
###############################################################################
* text eol=lf

###############################################################################
# Set explicit file behavior to:
# treat as text and
# normalize to Unix-style line endings
###############################################################################
*.asm text eol=lf
*.c text eol=lf
*.clj text eol=lf
Expand Down Expand Up @@ -49,19 +53,35 @@
*.txt text eol=lf
*.vb text eol=lf
*.yml text eol=lf
###############################################################################
# Set explicit file behavior to:
# treat as text
# normalize to Unix-style line endings and
# diff as csharp
###############################################################################
*.cs text eol=lf diff=csharp
###############################################################################
# Set explicit file behavior to:
# treat as text
# normalize to Unix-style line endings and
# use a union merge when resoling conflicts
###############################################################################
*.csproj text eol=lf merge=union
*.dbproj text eol=lf merge=union
*.fsproj text eol=lf merge=union
*.ncrunchproject text eol=lf merge=union
*.vbproj text eol=lf merge=union
###############################################################################
# Set explicit file behavior to:
# treat as text
# normalize to Windows-style line endings and
# use a union merge when resoling conflicts
###############################################################################
*.sln text eol=crlf merge=union
###############################################################################
# Set explicit file behavior to:
# treat as binary
###############################################################################
*.basis binary
*.bmp binary
*.dds binary
Expand Down Expand Up @@ -90,20 +110,15 @@
*.woff2 binary
*.xls binary
*.xlsx binary
###############################################################################
# Set explicit file behavior to:
# diff as plain text
###############################################################################
*.doc diff=astextplain
*.docx diff=astextplain
*.dot diff=astextplain
*.pdf diff=astextplain
*.pptx diff=astextplain
*.rtf diff=astextplain
*.svg diff=astextplain
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.jpg,*.jpeg,*.bmp,*.gif,*.png,*.tif,*.tiff,*.tga,*.webp filter=lfs diff=lfs merge=lfs -text
2 changes: 1 addition & 1 deletion shared-infrastructure
4 changes: 2 additions & 2 deletions src/ImageSharp/ColorSpaces/YCbCr.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

using System;
Expand Down Expand Up @@ -100,4 +100,4 @@ public bool Equals(YCbCr other)
&& this.Cr.Equals(other.Cr);
}
}
}
}
26 changes: 26 additions & 0 deletions src/ImageSharp/Processing/BinaryThresholdColorComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Processing
{
/// <summary>
/// The color component to be compared to threshold.
/// </summary>
public enum BinaryThresholdColorComponent : int
{
/// <summary>
/// Luminance color component according to ITU-R Recommendation BT.709.
/// </summary>
Luminance = 0,

/// <summary>
/// HSL saturation color component.
/// </summary>
Saturation = 1,

/// <summary>
/// Maximum of YCbCr chroma value, i.e. Cb and Cr distance from achromatic value.
/// </summary>
MaxChroma = 2,
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

using SixLabors.ImageSharp.Processing.Processors.Binarization;
Expand All @@ -11,29 +11,77 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
public static class BinaryThresholdExtensions
{
/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
/// Luminance as the color component to be compared to 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>
/// <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));

/// <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>
/// <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));

/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
/// Luminance as the color component to be compared to 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="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </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));
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdColorComponent.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="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
Rectangle rectangle) =>
source.ApplyProcessor(new BinaryThresholdProcessor(threshold), rectangle);
BinaryThresholdColorComponent colorComponent,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, colorComponent), rectangle);

/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
/// Luminance as the color component to be compared to 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="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>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
Color upperColor,
Color lowerColor)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance));

/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
Expand All @@ -42,13 +90,35 @@ public static IImageProcessingContext BinaryThreshold(
/// <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>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext BinaryThreshold(
this IImageProcessingContext source,
float threshold,
Color upperColor,
Color lowerColor) =>
source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor));
Color lowerColor,
BinaryThresholdColorComponent colorComponent)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, colorComponent));

/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold with
/// Luminance as the color component to be compared to 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="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="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </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,
Rectangle rectangle)
=> source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance), rectangle);

/// <summary>
/// Applies binarization to the image splitting the pixels at the given threshold.
Expand All @@ -57,6 +127,7 @@ public static IImageProcessingContext BinaryThreshold(
/// <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="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
Expand All @@ -66,7 +137,8 @@ public static IImageProcessingContext BinaryThreshold(
float threshold,
Color upperColor,
Color lowerColor,
BinaryThresholdColorComponent colorComponent,
Rectangle rectangle) =>
source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor), rectangle);
source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, colorComponent), rectangle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ public class BinaryThresholdProcessor : IImageProcessor
/// 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)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BinaryThresholdProcessor"/> class with
/// Luminance as color component to be compared to threshold.
/// </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)
: this(threshold, Color.White, Color.Black, BinaryThresholdColorComponent.Luminance)
{
}

Expand All @@ -25,12 +36,26 @@ public BinaryThresholdProcessor(float threshold)
/// <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>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor)
/// <param name="colorComponent">The color component to be compared to threshold.</param>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor, BinaryThresholdColorComponent colorComponent)
{
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold));
this.Threshold = threshold;
this.UpperColor = upperColor;
this.LowerColor = lowerColor;
this.ColorComponent = colorComponent;
}

/// <summary>
/// Initializes a new instance of the <see cref="BinaryThresholdProcessor"/> class with
/// Luminance as color component to be compared to threshold.
/// </summary>
/// <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>
public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor)
: this(threshold, upperColor, lowerColor, BinaryThresholdColorComponent.Luminance)
{
}

/// <summary>
Expand All @@ -48,7 +73,12 @@ public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerCo
/// </summary>
public Color LowerColor { get; }

/// <inheritdoc />
/// <summary>
/// Gets a value indicating whether to use saturation value instead of luminance.
/// </summary>
public BinaryThresholdColorComponent ColorComponent { get; }

/// <inheritdoc />
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle)
where TPixel : unmanaged, IPixel<TPixel>
=> new BinaryThresholdProcessor<TPixel>(configuration, this, source, sourceRectangle);
Expand Down
Loading

0 comments on commit 6038be9

Please sign in to comment.