mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2025-12-13 01:58:30 +00:00
Moved comparison, blending and conversion from color to a behavior-class to make it exchangeable
This commit is contained in:
parent
fa396127ea
commit
5d374db9ef
80
RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
Normal file
80
RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
namespace RGB.NET.Core
|
||||||
|
{
|
||||||
|
public class DefaultColorBehavior : IColorBehavior
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private static DefaultColorBehavior _instance = new DefaultColorBehavior();
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the singleton instance of <see cref="DefaultColorBehavior"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static DefaultColorBehavior Instance { get; } = _instance;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
private DefaultColorBehavior()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the individual byte values of this <see cref="Color"/> to a human-readable string.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string that contains the individual byte values of this <see cref="Color"/>. For example "[A: 255, R: 255, G: 0, B: 0]".</returns>
|
||||||
|
public virtual string ToString(Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests whether the specified object is a <see cref="Color" /> and is equivalent to this <see cref="Color" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to test.</param>
|
||||||
|
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
|
||||||
|
public virtual bool Equals(Color color, object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Color)) return false;
|
||||||
|
|
||||||
|
(double a, double r, double g, double b) = ((Color)obj).GetRGB();
|
||||||
|
return color.A.EqualsInTolerance(a) && color.R.EqualsInTolerance(r) && color.G.EqualsInTolerance(g) && color.B.EqualsInTolerance(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a hash code for this <see cref="Color" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
|
||||||
|
public virtual int GetHashCode(Color color)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hashCode = color.A.GetHashCode();
|
||||||
|
hashCode = (hashCode * 397) ^ color.R.GetHashCode();
|
||||||
|
hashCode = (hashCode * 397) ^ color.G.GetHashCode();
|
||||||
|
hashCode = (hashCode * 397) ^ color.B.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blends a <see cref="Color"/> over this color.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The <see cref="Color"/> to blend.</param>
|
||||||
|
public virtual Color Blend(Color baseColor, Color blendColor)
|
||||||
|
{
|
||||||
|
if (blendColor.A.EqualsInTolerance(0)) return baseColor;
|
||||||
|
|
||||||
|
if (blendColor.A.EqualsInTolerance(1))
|
||||||
|
return blendColor;
|
||||||
|
|
||||||
|
double resultA = (1.0 - ((1.0 - blendColor.A) * (1.0 - baseColor.A)));
|
||||||
|
double resultR = (((blendColor.R * blendColor.A) / resultA) + ((baseColor.R * baseColor.A * (1.0 - blendColor.A)) / resultA));
|
||||||
|
double resultG = (((blendColor.G * blendColor.A) / resultA) + ((baseColor.G * baseColor.A * (1.0 - blendColor.A)) / resultA));
|
||||||
|
double resultB = (((blendColor.B * blendColor.A) / resultA) + ((baseColor.B * baseColor.A * (1.0 - blendColor.A)) / resultA));
|
||||||
|
|
||||||
|
return new Color(resultA, resultR, resultG, resultB);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
13
RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
Normal file
13
RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace RGB.NET.Core
|
||||||
|
{
|
||||||
|
public interface IColorBehavior
|
||||||
|
{
|
||||||
|
string ToString(Color color);
|
||||||
|
|
||||||
|
bool Equals(Color color, object obj);
|
||||||
|
|
||||||
|
int GetHashCode(Color color);
|
||||||
|
|
||||||
|
Color Blend(Color baseColor, Color blendColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,6 +25,16 @@ namespace RGB.NET.Core
|
|||||||
|
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private static IColorBehavior _behavior = DefaultColorBehavior.Instance;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="IColorBehavior"/> used to perform operations on colors.
|
||||||
|
/// </summary>
|
||||||
|
public static IColorBehavior Behavior
|
||||||
|
{
|
||||||
|
get => _behavior;
|
||||||
|
set => _behavior = value ?? DefaultColorBehavior.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the alpha component value of this <see cref="Color"/> as percentage in the range [0..1].
|
/// Gets the alpha component value of this <see cref="Color"/> as percentage in the range [0..1].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -179,62 +189,29 @@ namespace RGB.NET.Core
|
|||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts the individual byte values of this <see cref="Color"/> to a human-readable string.
|
/// Gets a human-readable string, as defined by the current <see cref="Behavior"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A string that contains the individual byte values of this <see cref="Color"/>. For example "[A: 255, R: 255, G: 0, B: 0]".</returns>
|
/// <returns>A string that contains the individual byte values of this <see cref="Color"/>. Default format: "[A: 255, R: 255, G: 0, B: 0]".</returns>
|
||||||
public override string ToString() => $"[A: {this.GetA()}, R: {this.GetR()}, G: {this.GetG()}, B: {this.GetB()}]";
|
public override string ToString() => Behavior.ToString(this);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests whether the specified object is a <see cref="Color" /> and is equivalent to this <see cref="Color" />.
|
/// Tests whether the specified object is a <see cref="Color" /> and is equivalent to this <see cref="Color" />, as defined by the current <see cref="Behavior"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object to test.</param>
|
/// <param name="obj">The object to test.</param>
|
||||||
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj) => Behavior.Equals(this, obj);
|
||||||
{
|
|
||||||
if (!(obj is Color)) return false;
|
|
||||||
|
|
||||||
(double a, double r, double g, double b) = ((Color)obj).GetRGB();
|
|
||||||
return A.EqualsInTolerance(a) && R.EqualsInTolerance(r) && G.EqualsInTolerance(g) && B.EqualsInTolerance(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a hash code for this <see cref="Color" />.
|
/// Returns a hash code for this <see cref="Color" />, as defined by the current <see cref="Behavior"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
|
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
|
||||||
public override int GetHashCode()
|
public override int GetHashCode() => Behavior.GetHashCode(this);
|
||||||
{
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
int hashCode = A.GetHashCode();
|
|
||||||
hashCode = (hashCode * 397) ^ R.GetHashCode();
|
|
||||||
hashCode = (hashCode * 397) ^ G.GetHashCode();
|
|
||||||
hashCode = (hashCode * 397) ^ B.GetHashCode();
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Manipulation
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Blends a <see cref="Color"/> over this color.
|
/// Blends a <see cref="Color"/> over this color, as defined by the current <see cref="Behavior"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="color">The <see cref="Color"/> to blend.</param>
|
/// <param name="color">The <see cref="Color"/> to blend.</param>
|
||||||
public Color Blend(Color color)
|
public Color Blend(Color color) => Behavior.Blend(this, color);
|
||||||
{
|
|
||||||
if (color.A.EqualsInTolerance(0)) return this;
|
|
||||||
|
|
||||||
if (color.A.EqualsInTolerance(1))
|
|
||||||
return color;
|
|
||||||
|
|
||||||
double resultA = (1.0 - ((1.0 - color.A) * (1.0 - A)));
|
|
||||||
double resultR = (((color.R * color.A) / resultA) + ((R * A * (1.0 - color.A)) / resultA));
|
|
||||||
double resultG = (((color.G * color.A) / resultA) + ((G * A * (1.0 - color.A)) / resultA));
|
|
||||||
double resultB = (((color.B * color.A) / resultA) + ((B * A * (1.0 - color.A)) / resultA));
|
|
||||||
|
|
||||||
return new Color(resultA, resultR, resultG, resultB);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=brushes/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=brushes/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=color/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=color/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=colorcorrection/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=colorcorrection/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=color_005Cbehaviors/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=decorators/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=decorators/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices_005Cupdate/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=devices_005Cupdate/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user