diff --git a/RGB.NET.Brushes/Gradients/RainbowGradient.cs b/RGB.NET.Brushes/Gradients/RainbowGradient.cs
index b99a87a..01946d0 100644
--- a/RGB.NET.Brushes/Gradients/RainbowGradient.cs
+++ b/RGB.NET.Brushes/Gradients/RainbowGradient.cs
@@ -73,10 +73,8 @@ namespace RGB.NET.Brushes.Gradients
public Color GetColor(double offset)
{
double range = EndHue - StartHue;
- double hue = (StartHue + (range * offset)) % 360f;
- if (hue < 0)
- hue += 360;
- return Color.FromHSV(hue, 1, 1);
+ double hue = StartHue + (range * offset);
+ return HSVColor.Create(hue, 1, 1);
}
///
@@ -87,7 +85,7 @@ namespace RGB.NET.Brushes.Gradients
StartHue += offset;
EndHue += offset;
-
+
while ((StartHue > 360) && (EndHue > 360))
{
StartHue -= 360;
diff --git a/RGB.NET.Core/Brushes/AbstractBrush.cs b/RGB.NET.Core/Brushes/AbstractBrush.cs
index 716cc4a..0c6591a 100644
--- a/RGB.NET.Core/Brushes/AbstractBrush.cs
+++ b/RGB.NET.Core/Brushes/AbstractBrush.cs
@@ -115,7 +115,7 @@ namespace RGB.NET.Core
// Since we use HSV to calculate there is no way to make a color 'brighter' than 100%
// Be carefull with the naming: Since we use HSV the correct term is 'value' but outside we call it 'brightness'
// THIS IS NOT A HSB CALCULATION!!!
- return color.MultiplyValue(Brightness.Clamp(0, 1))
+ return color.MultiplyHSV(value: Brightness.Clamp(0, 1))
.MultiplyA(Opacity.Clamp(0, 1));
}
diff --git a/RGB.NET.Core/Color/Color.cs b/RGB.NET.Core/Color/Color.cs
new file mode 100644
index 0000000..3c0667e
--- /dev/null
+++ b/RGB.NET.Core/Color/Color.cs
@@ -0,0 +1,334 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable UnusedMethodReturnValue.Global
+
+using System;
+using System.Diagnostics;
+
+namespace RGB.NET.Core
+{
+ ///
+ ///
+ /// Represents an ARGB (alpha, red, green, blue) color.
+ ///
+ [DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")]
+ public struct Color
+ {
+ #region Constants
+
+ ///
+ /// Gets an transparent color [A: 0, R: 0, G: 0, B: 0]
+ ///
+ public static Color Transparent => new Color(0, 0, 0, 0);
+
+ #endregion
+
+ #region Properties & Fields
+
+ ///
+ /// Gets the alpha component value of this as byte in the range [0..255].
+ ///
+ public byte A { get; }
+
+ ///
+ /// Gets the alpha component value of this as percentage in the range [0..1].
+ ///
+ public double APercent { get; }
+
+ ///
+ /// Gets the red component value of this as byte in the range [0..255].
+ ///
+ public byte R { get; }
+
+ ///
+ /// Gets the red component value of this as percentage in the range [0..1].
+ ///
+ public double RPercent { get; }
+
+ ///
+ /// Gets the green component value of this as byte in the range [0..255].
+ ///
+ public byte G { get; }
+
+ ///
+ /// Gets the green component value of this as percentage in the range [0..1].
+ ///
+ public double GPercent { get; }
+
+ ///
+ /// Gets the blue component value of this as byte in the range [0..255].
+ ///
+ public byte B { get; }
+
+ ///
+ /// Gets the blue component value of this as percentage in the range [0..1].
+ ///
+ public double BPercent { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the struct using RGB-Values.
+ /// Alpha defaults to 255.
+ ///
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(byte r, byte g, byte b)
+ : this(byte.MaxValue, r, g, b)
+ { }
+
+ ///
+ ///
+ /// Initializes a new instance of the struct using RGB-Values.
+ /// Alpha defaults to 255.
+ ///
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(int r, int g, int b)
+ : this((byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(byte a, byte r, byte g, byte b)
+ : this(a, r, g, b, a.GetPercentageFromByteValue(), r.GetPercentageFromByteValue(), g.GetPercentageFromByteValue(), b.GetPercentageFromByteValue())
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(int a, int r, int g, int b)
+ : this((byte)a.Clamp(0, byte.MaxValue), (byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using RGB-percent values.
+ /// Alpha defaults to 1.0.
+ ///
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(double r, double g, double b)
+ : this(1.0, r, g, b)
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB-percent values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(double a, byte r, byte g, byte b)
+ : this(a.GetByteValueFromPercentage(), r, g, b,
+ a.Clamp(0, 1), r.GetPercentageFromByteValue(), g.GetPercentageFromByteValue(), b.GetPercentageFromByteValue())
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB-percent values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(double a, int r, int g, int b)
+ : this(a, (byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB-percent values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(int a, double r, double g, double b)
+ : this((byte)a.Clamp(0, byte.MaxValue), r, g, b)
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB-percent values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(byte a, double r, double g, double b)
+ : this(a, r.GetByteValueFromPercentage(), g.GetByteValueFromPercentage(), b.GetByteValueFromPercentage(),
+ a.GetPercentageFromByteValue(), r.Clamp(0, 1), g.Clamp(0, 1), b.Clamp(0, 1))
+ { }
+
+ ///
+ /// Initializes a new instance of the struct using ARGB-percent values.
+ ///
+ /// The alpha component value of this .
+ /// The red component value of this .
+ /// The green component value of this .
+ /// The blue component value of this .
+ public Color(double a, double r, double g, double b)
+ : this(a.GetByteValueFromPercentage(), r.GetByteValueFromPercentage(), g.GetByteValueFromPercentage(), b.GetByteValueFromPercentage(),
+ a.Clamp(0, 1), r.Clamp(0, 1), g.Clamp(0, 1), b.Clamp(0, 1))
+ { }
+
+ ///
+ ///
+ /// Initializes a new instance of the struct by cloning a existing .
+ ///
+ /// The the values are copied from.
+ public Color(Color color)
+ : this(color.APercent, color.RPercent, color.GPercent, color.BPercent)
+ { }
+
+ private Color(byte a, byte r, byte g, byte b, double aP, double rP, double gP, double bP)
+ {
+ this.A = a;
+ this.R = r;
+ this.G = g;
+ this.B = b;
+
+ this.APercent = aP;
+ this.RPercent = rP;
+ this.GPercent = gP;
+ this.BPercent = bP;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Converts the individual byte values of this to a human-readable string.
+ ///
+ /// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]".
+ public override string ToString() => $"[A: {A}, R: {R}, G: {G}, B: {B}]";
+
+ ///
+ /// Tests whether the specified object is a and is equivalent to this .
+ ///
+ /// The object to test.
+ /// true if is a equivalent to this ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ if (!(obj is Color)) return false;
+
+ (byte a, byte r, byte g, byte b) = (Color)obj;
+ return (a == A) && (r == R) && (g == G) && (b == B);
+ }
+
+ ///
+ /// Returns a hash code for this .
+ ///
+ /// An integer value that specifies the hash code for this .
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = APercent.GetHashCode();
+ hashCode = (hashCode * 397) ^ RPercent.GetHashCode();
+ hashCode = (hashCode * 397) ^ GPercent.GetHashCode();
+ hashCode = (hashCode * 397) ^ BPercent.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ #region Deconstruction
+
+ ///
+ /// Deconstructs the Color into it's ARGB-components.
+ ///
+ /// The alpha component of this color.
+ /// The red component of this color.
+ /// The green component of this color.
+ /// The blue component of this color.
+ public void Deconstruct(out byte a, out byte r, out byte g, out byte b)
+ {
+ a = A;
+ r = R;
+ g = G;
+ b = B;
+ }
+
+ #endregion
+
+ #region Manipulation
+
+ ///
+ /// Blends a over this color.
+ ///
+ /// The to blend.
+ public Color Blend(Color color)
+ {
+ if (color.A == 0) return this;
+
+ if (color.A == 255)
+ return color;
+
+ double resultA = (1.0 - ((1.0 - color.APercent) * (1.0 - APercent)));
+ double resultR = (((color.RPercent * color.APercent) / resultA) + ((RPercent * APercent * (1.0 - color.APercent)) / resultA));
+ double resultG = (((color.GPercent * color.APercent) / resultA) + ((GPercent * APercent * (1.0 - color.APercent)) / resultA));
+ double resultB = (((color.BPercent * color.APercent) / resultA) + ((BPercent * APercent * (1.0 - color.APercent)) / resultA));
+
+ return new Color(resultA, resultR, resultG, resultB);
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Operators
+
+ ///
+ /// Blends the provided colors as if would've been called on .
+ ///
+ /// The base color.
+ /// The color to blend.
+ /// The blended color.
+ public static Color operator +(Color color1, Color color2) => color1.Blend(color2);
+
+ ///
+ /// Returns a value that indicates whether two specified are equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ /// true if and are equal; otherwise, false.
+ public static bool operator ==(Color color1, Color color2) => color1.Equals(color2);
+
+ ///
+ /// Returns a value that indicates whether two specified are equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ /// true if and are not equal; otherwise, false.
+ public static bool operator !=(Color color1, Color color2) => !(color1 == color2);
+
+ ///
+ /// Converts a of ARGB-components to a .
+ ///
+ /// The containing the components.
+ /// The color.
+ public static implicit operator Color((byte a, byte r, byte g, byte b) components) => new Color(components.a, components.r, components.g, components.b);
+
+ ///
+ /// Converts a of HSV-components to a .
+ ///
+ /// The containing the components.
+ /// The color.
+ public static implicit operator Color((double hue, double saturation, double value) components) => new Color(components.hue, components.saturation, components.value);
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Core/Color/HSVColor.cs b/RGB.NET.Core/Color/HSVColor.cs
new file mode 100644
index 0000000..e632e6c
--- /dev/null
+++ b/RGB.NET.Core/Color/HSVColor.cs
@@ -0,0 +1,203 @@
+using System;
+
+namespace RGB.NET.Core
+{
+ public static class HSVColor
+ {
+ #region Getter
+
+ public static double GetHue(this Color color) => color.GetHSV().hue;
+
+ public static double GetSaturation(this Color color) => color.GetHSV().saturation;
+
+ public static double GetValue(this Color color) => color.GetHSV().value;
+
+ public static (double hue, double saturation, double value) GetHSV(this Color color)
+ => CaclulateHSVFromRGB(color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Manipulation
+
+ ///
+ /// Adds the given HSV values to this color.
+ ///
+ /// The hue value to add.
+ /// The saturation value to add.
+ /// The value value to add.
+ /// The new color after the modification.
+ public static Color AddHSV(this Color color, double hue = 0, double saturation = 0, double value = 0)
+ {
+ (double cHue, double cSaturation, double cValue) = color.GetHSV();
+ return Create(color.APercent, cHue + hue, cSaturation + saturation, cValue + value);
+ }
+
+ ///
+ /// Subtracts the given HSV values to this color.
+ ///
+ /// The hue value to subtract.
+ /// The saturation value to subtract.
+ /// The value value to subtract.
+ /// The new color after the modification.
+ public static Color SubtractHSV(this Color color, double hue = 0, double saturation = 0, double value = 0)
+ {
+ (double cHue, double cSaturation, double cValue) = color.GetHSV();
+ return Create(color.APercent, cHue - hue, cSaturation - saturation, cValue - value);
+ }
+
+ ///
+ /// Multiplies the given HSV values to this color.
+ ///
+ /// The hue value to multiply.
+ /// The saturation value to multiply.
+ /// The value value to multiply.
+ /// The new color after the modification.
+ public static Color MultiplyHSV(this Color color, double hue = 1, double saturation = 1, double value = 1)
+ {
+ (double cHue, double cSaturation, double cValue) = color.GetHSV();
+ return Create(color.APercent, cHue * hue, cSaturation * saturation, cValue * value);
+ }
+
+
+ ///
+ /// Divides the given HSV values to this color.
+ ///
+ /// The hue value to divide.
+ /// The saturation value to divide.
+ /// The value value to divide.
+ /// The new color after the modification.
+ public static Color DivideHSV(this Color color, double hue = 1, double saturation = 1, double value = 1)
+ {
+ (double cHue, double cSaturation, double cValue) = color.GetHSV();
+ return Create(color.APercent, cHue / hue, cSaturation / saturation, cValue / value);
+ }
+
+ ///
+ /// Sets the given hue value of this color.
+ ///
+ /// The hue value to set.
+ /// The saturation value to set.
+ /// The value value to set.
+ /// The new color after the modification.
+ public static Color SetHSV(this Color color, double? hue = null, double? saturation = null, double? value = null)
+ {
+ (double cHue, double cSaturation, double cValue) = color.GetHSV();
+ return Create(color.APercent, hue ?? cHue, saturation ?? cSaturation, value ?? cValue);
+ }
+
+ #endregion
+
+ #region Factory
+
+ ///
+ /// Creates a new instance of the struct using HSV-Values.
+ ///
+ /// The hue component value of this .
+ /// The saturation component value of this .
+ /// The value component value of this .
+ /// The color created from the values.
+ public static Color Create(double hue, double saturation, double value)
+ => Create(1.0, hue, saturation, value);
+
+ ///
+ /// Creates a new instance of the struct using AHSV-Values.
+ ///
+ /// The alpha component value of this .
+ /// The hue component value of this .
+ /// The saturation component value of this .
+ /// The value component value of this .
+ /// The color created from the values.
+ public static Color Create(byte a, double hue, double saturation, double value)
+ => Create((double)a / byte.MaxValue, hue, saturation, value);
+
+ ///
+ /// Creates a new instance of the struct using AHSV-Values.
+ ///
+ /// The alpha component value of this .
+ /// The hue component value of this .
+ /// The saturation component value of this .
+ /// The value component value of this .
+ /// The color created from the values.
+ public static Color Create(int a, double hue, double saturation, double value)
+ => Create((double)a / byte.MaxValue, hue, saturation, value);
+
+ ///
+ /// Creates a new instance of the struct using AHSV-Values.
+ ///
+ /// The alpha component value of this .
+ /// The hue component value of this .
+ /// The saturation component value of this .
+ /// The value component value of this .
+ /// The color created from the values.
+ public static Color Create(double a, double hue, double saturation, double value)
+ {
+ (double r, double g, double b) = CalculateRGBFromHSV(hue, saturation, value);
+ return new Color(a, r, g, b);
+ }
+
+ #endregion
+
+ #region Helper
+
+ private static (double h, double s, double v) CaclulateHSVFromRGB(double r, double g, double b)
+ {
+ if ((r == g) && (g == b)) return (0, 0, r);
+
+ double min = Math.Min(Math.Min(r, g), b);
+ double max = Math.Max(Math.Max(r, g), b);
+
+ double hue;
+ if (max == min)
+ hue = 0;
+ else if (max == r) // r is max
+ hue = (g - b) / (max - min);
+ else if (max == g) // g is max
+ hue = 2.0 + ((b - r) / (max - min));
+ else // b is max
+ hue = 4.0 + ((r - g) / (max - min));
+
+ hue = hue * 60.0;
+ hue = hue.Wrap(0, 360);
+
+ double saturation = (max == 0) ? 0 : 1.0 - (min / max);
+ double value = Math.Max(r, Math.Max(g, b));
+
+ return (hue, saturation, value);
+ }
+
+ private static (double r, double g, double b) CalculateRGBFromHSV(double h, double s, double v)
+ {
+ h = h.Wrap(0, 360);
+ s = s.Clamp(0, 1);
+ v = v.Clamp(0, 1);
+
+ if (s <= 0.0)
+ return (v, v, v);
+
+ double hh = h / 60.0;
+ int i = (int)hh;
+ double ff = hh - i;
+ double p = v * (1.0 - s);
+ double q = v * (1.0 - (s * ff));
+ double t = v * (1.0 - (s * (1.0 - ff)));
+
+ switch (i)
+ {
+ case 0:
+ return (v, t, p);
+ case 1:
+ return (q, v, p);
+ case 2:
+ return (p, v, t);
+ case 3:
+ return (p, q, v);
+ case 4:
+ return (t, p, v);
+ default:
+ return (v, p, q);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Core/Color/RGBColor.cs b/RGB.NET.Core/Color/RGBColor.cs
new file mode 100644
index 0000000..fa26417
--- /dev/null
+++ b/RGB.NET.Core/Color/RGBColor.cs
@@ -0,0 +1,232 @@
+using System;
+
+namespace RGB.NET.Core
+{
+ public static class RGBColor
+ {
+ #region Getter
+
+ public static (double r, double g, double b) GetRGBPercent(this Color color)
+ => (color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Manipulation
+
+ #region Add
+
+ ///
+ /// Adds the given RGB values to this color.
+ ///
+ /// The red value to add.
+ /// The green value to add.
+ /// The blue value to add.
+ /// The new color after the modification.
+ public static Color AddRGB(this Color color, int r = 0, int g = 0, int b = 0)
+ => new Color(color.APercent, color.R + r, color.G + g, color.B + b);
+
+ ///
+ /// Adds the given RGB-percent values to this color.
+ ///
+ /// The red value to add.
+ /// The green value to add.
+ /// The blue value to add.
+ /// The new color after the modification.
+ public static Color AddRGB(this Color color, double r = 0, double g = 0, double b = 0)
+ => new Color(color.APercent, color.RPercent + r, color.GPercent + g, color.BPercent + b);
+
+ ///
+ /// Adds the given alpha value to this color.
+ ///
+ /// The alpha value to add.
+ /// The new color after the modification.
+ public static Color AddA(this Color color, int a)
+ => new Color(color.A + a, color.RPercent, color.GPercent, color.BPercent);
+
+ ///
+ /// Adds the given alpha-percent value to this color.
+ ///
+ /// The alpha value to add.
+ /// The new color after the modification.
+ public static Color AddA(this Color color, double a)
+ => new Color(color.APercent + a, color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Subtract
+
+ ///
+ /// Subtracts the given RGB values to this color.
+ ///
+ /// The red value to subtract.
+ /// The green value to subtract.
+ /// The blue value to subtract.
+ /// The new color after the modification.
+ public static Color SubtractRGB(this Color color, int r = 0, int g = 0, int b = 0)
+ => new Color(color.APercent, color.R - r, color.G - g, color.B - b);
+
+ ///
+ /// Subtracts the given RGB values to this color.
+ ///
+ /// The red value to subtract.
+ /// The green value to subtract.
+ /// The blue value to subtract.
+ /// The new color after the modification.
+ public static Color SubtractRGB(this Color color, double r = 0, double g = 0, double b = 0)
+ => new Color(color.APercent, color.RPercent - r, color.GPercent - g, color.BPercent - b);
+
+ ///
+ /// Subtracts the given alpha value to this color.
+ ///
+ /// The alpha value to subtract.
+ /// The new color after the modification.
+ public static Color SubtractA(this Color color, int a)
+ => new Color(color.A - a, color.RPercent, color.GPercent, color.BPercent);
+
+ ///
+ /// Subtracts the given alpha-percent value to this color.
+ ///
+ /// The alpha value to subtract.
+ /// The new color after the modification.
+ public static Color SubtractA(this Color color, double aPercent)
+ => new Color(color.APercent - aPercent, color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Multiply
+
+ ///
+ /// Multiplies the given RGB values to this color.
+ ///
+ /// The red value to multiply.
+ /// The green value to multiply.
+ /// The blue value to multiply.
+ /// The new color after the modification.
+ public static Color MultiplyRGB(this Color color, double r = 1, double g = 1, double b = 1)
+ => new Color(color.APercent, color.RPercent * r, color.GPercent * g, color.BPercent * b);
+
+ ///
+ /// Multiplies the given alpha value to this color.
+ ///
+ /// The alpha value to multiply.
+ /// The new color after the modification.
+ public static Color MultiplyA(this Color color, double a)
+ => new Color(color.APercent * a, color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Divide
+
+ ///
+ /// Divides the given RGB values to this color.
+ ///
+ /// The red value to divide.
+ /// The green value to divide.
+ /// The blue value to divide.
+ /// The new color after the modification.
+ public static Color DivideRGB(this Color color, double r = 1, double g = 1, double b = 1)
+ => new Color(color.APercent, color.RPercent / r, color.GPercent / g, color.BPercent / b);
+
+ ///
+ /// Divides the given alpha value to this color.
+ ///
+ /// The alpha value to divide.
+ /// The new color after the modification.
+ public static Color DivideA(this Color color, double a)
+ => new Color(color.APercent / a, color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #region Set
+
+ ///
+ /// Sets the given RGB value of this color.
+ ///
+ /// The red value to set.
+ /// The green value to set.
+ /// The blue value to set.
+ /// The new color after the modification.
+ public static Color SetRGB(this Color color, byte? r = null, byte? g = null, byte? b = null)
+ => new Color(color.APercent, r ?? color.R, g ?? color.G, b ?? color.B);
+
+ ///
+ /// Sets the given RGB value of this color.
+ ///
+ /// The red value to set.
+ /// The green value to set.
+ /// The blue value to set.
+ /// The new color after the modification.
+ public static Color SetRGB(this Color color, int? r = null, int? g = null, int? b = null)
+ => new Color(color.APercent, r ?? color.R, g ?? color.G, b ?? color.B);
+
+ ///
+ /// Sets the given RGB value of this color.
+ ///
+ /// The red value to set.
+ /// The green value to set.
+ /// The blue value to set.
+ /// The new color after the modification.
+ public static Color SetRGB(this Color color, double? r = null, double? g = null, double? b = null)
+ => new Color(color.APercent, r ?? color.RPercent, g ?? color.GPercent, b ?? color.BPercent);
+
+ ///
+ /// Sets the given alpha value of this color.
+ ///
+ /// The alpha value to set.
+ /// The new color after the modification.
+ public static Color SetA(this Color color, int a) => new Color(a, color.RPercent, color.GPercent, color.BPercent);
+
+ ///
+ /// Sets the given alpha value of this color.
+ ///
+ /// The alpha value to set.
+ /// The new color after the modification.
+ public static Color SetA(this Color color, double a) => new Color(a, color.RPercent, color.GPercent, color.BPercent);
+
+ #endregion
+
+ #endregion
+
+ #region Conversion
+
+ ///
+ /// Gets the current color as a RGB-HEX-string.
+ ///
+ /// The RGB-HEX-string.
+ public static string AsRGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.R, color.G, color.B);
+
+ ///
+ /// Gets the current color as a ARGB-HEX-string.
+ ///
+ /// The ARGB-HEX-string.
+ public static string AsARGBHexString(this Color color, bool leadingHash = true) => (leadingHash ? "#" : "") + ConversionHelper.ToHex(color.A, color.R, color.G, color.B);
+
+ #endregion
+
+ #region Factory
+
+ ///
+ /// Creates a new instance of the struct using a HEX-string.
+ ///
+ /// The HEX-representation of the color.
+ /// The color created from the HEX-string.
+ public static Color FromHexString(string hexString)
+ {
+ if ((hexString == null) || (hexString.Length < 6))
+ throw new ArgumentException("Invalid hex string", nameof(hexString));
+
+ if (hexString[0] == '#')
+ hexString = hexString.Substring(1);
+
+ byte[] data = ConversionHelper.HexToBytes(hexString);
+ if (data.Length == 3)
+ return new Color(data[0], data[1], data[2]);
+ if (data.Length == 4)
+ return new Color(data[0], data[1], data[2], data[3]);
+
+ throw new ArgumentException("Invalid hex string", nameof(hexString));
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Core/Extensions/MathExtensions.cs b/RGB.NET.Core/Extensions/MathExtensions.cs
index 397d297..0a9fb88 100644
--- a/RGB.NET.Core/Extensions/MathExtensions.cs
+++ b/RGB.NET.Core/Extensions/MathExtensions.cs
@@ -36,7 +36,14 @@ namespace RGB.NET.Core
/// The higher value of the range the value is clamped to.
/// The clamped value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static double Clamp(this double value, double min, double max) => Math.Max(min, Math.Min(max, value));
+ public static double Clamp(this double value, double min, double max)
+ {
+ // ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
+ if (value < min) return min;
+ if (value > max) return max;
+ return value;
+ // ReSharper restore ConvertIfStatementToReturnStatement
+ }
///
/// Clamps the provided value to be bigger or equal min and smaller or equal max.
@@ -46,7 +53,14 @@ namespace RGB.NET.Core
/// The higher value of the range the value is clamped to.
/// The clamped value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Clamp(this int value, int min, int max) => Math.Max(min, Math.Min(max, value));
+ public static int Clamp(this int value, int min, int max)
+ {
+ // ReSharper disable ConvertIfStatementToReturnStatement - I'm not sure why, but inlining this statement reduces performance by ~10%
+ if (value < min) return min;
+ if (value > max) return max;
+ return value;
+ // ReSharper restore ConvertIfStatementToReturnStatement
+ }
///
/// Enforces the provided value to be in the specified range by wrapping it around the edges if it exceeds them.
@@ -78,6 +92,10 @@ namespace RGB.NET.Core
return (byte)(percentage >= 1.0 ? 255 : percentage * 256.0);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double GetPercentageFromByteValue(this byte value)
+ => ((double)value) / byte.MaxValue;
+
#endregion
}
}
diff --git a/RGB.NET.Core/Leds/Color.cs b/RGB.NET.Core/Leds/Color.cs
deleted file mode 100644
index cc2208d..0000000
--- a/RGB.NET.Core/Leds/Color.cs
+++ /dev/null
@@ -1,1124 +0,0 @@
-// ReSharper disable MemberCanBePrivate.Global
-// ReSharper disable UnusedMember.Global
-// ReSharper disable UnusedMethodReturnValue.Global
-
-using System;
-using System.Diagnostics;
-
-namespace RGB.NET.Core
-{
- ///
- ///
- /// Represents an ARGB (alpha, red, green, blue) color.
- ///
- [DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}, H: {Hue}, S: {Saturation}, V: {Value}]")]
- public struct Color
- {
- #region Constants
-
- ///
- /// Gets an transparent color [A: 0, R: 0, G: 0, B: 0]
- ///
- public static Color Transparent => new Color(0, 0, 0, 0);
-
- #endregion
-
- #region Properties & Fields
-
- #region RGB
-
- ///
- /// Gets the alpha component value of this as byte in the range [0..255].
- ///
- public byte A { get; }
-
- ///
- /// Gets the alpha component value of this as percentage in the range [0..1].
- ///
- public double APercent => A / (double)byte.MaxValue;
-
- ///
- /// Gets the red component value of this as byte in the range [0..255].
- ///
- public byte R { get; }
-
- ///
- /// Gets the red component value of this as percentage in the range [0..1].
- ///
- public double RPercent => R / (double)byte.MaxValue;
-
- ///
- /// Gets the green component value of this as byte in the range [0..255].
- ///
- public byte G { get; }
-
- ///
- /// Gets the green component value of this as percentage in the range [0..1].
- ///
- public double GPercent => G / (double)byte.MaxValue;
-
- ///
- /// Gets the blue component value of this as byte in the range [0..255].
- ///
- public byte B { get; }
-
- ///
- /// Gets the blue component value of this as percentage in the range [0..1].
- ///
- public double BPercent => B / (double)byte.MaxValue;
-
- #endregion
-
- #region HSV
-
- ///
- /// Gets the hue component value (HSV-color space) of this as degree in the range [0..360].
- ///
- public double Hue { get; }
-
- ///
- /// Gets the saturation component value (HSV-color space) of this as degree in the range [0..1].
- ///
- public double Saturation { get; }
-
- ///
- /// Gets the value component value (HSV-color space) of this as degree in the range [0..1].
- ///
- public double Value { get; }
-
- #endregion
-
- #endregion
-
- #region Constructors
-
- ///
- ///
- /// Initializes a new instance of the struct using RGB-Values.
- /// Alpha defaults to 255.
- ///
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(byte r, byte g, byte b)
- : this(byte.MaxValue, r, g, b)
- { }
-
- ///
- ///
- /// Initializes a new instance of the struct using RGB-Values.
- /// Alpha defaults to 255.
- ///
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(int r, int g, int b)
- : this((byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
- { }
-
- ///
- /// Initializes a new instance of the struct using ARGB values.
- ///
- /// The alpha component value of this .
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(byte a, byte r, byte g, byte b)
- {
- this.A = a;
- this.R = r;
- this.G = g;
- this.B = b;
-
- (double h, double s, double v) = CaclulateHSVFromRGB(r, g, b);
- Hue = h;
- Saturation = s;
- Value = v;
- }
-
- ///
- /// Initializes a new instance of the struct using ARGB values.
- ///
- /// The alpha component value of this .
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(int a, int r, int g, int b)
- : this((byte)a.Clamp(0, byte.MaxValue), (byte)r.Clamp(0, byte.MaxValue), (byte)g.Clamp(0, byte.MaxValue), (byte)b.Clamp(0, byte.MaxValue))
- { }
-
- ///
- /// Initializes a new instance of the struct using RGB-percent values.
- ///
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(double r, double g, double b)
- : this(byte.MaxValue,
- r.GetByteValueFromPercentage(),
- g.GetByteValueFromPercentage(),
- b.GetByteValueFromPercentage())
- { }
-
- ///
- /// Initializes a new instance of the struct using ARGB-percent values.
- ///
- /// The alpha component value of this .
- /// The red component value of this .
- /// The green component value of this .
- /// The blue component value of this .
- public Color(double a, double r, double g, double b)
- : this(a.GetByteValueFromPercentage(),
- r.GetByteValueFromPercentage(),
- g.GetByteValueFromPercentage(),
- b.GetByteValueFromPercentage())
- { }
-
- ///
- ///
- /// Initializes a new instance of the struct by cloning a existing .
- ///
- /// The the values are copied from.
- public Color(Color color)
- : this(color.A, color.R, color.G, color.B) { }
-
- #endregion
-
- #region Methods
-
- #region Factory
-
- ///
- /// Creates a new instance of the struct using HSV-Values.
- ///
- /// The hue component value of this .
- /// The saturation component value of this .
- /// The value component value of this .
- /// The color created from the values.
- public static Color FromHSV(double hue, double saturation, double value)
- {
- (byte r, byte g, byte b) = CalculateRGBFromHSV(hue, saturation, value);
- return new Color(r, g, b);
- }
-
- ///
- /// Creates a new instance of the struct using AHSV-Values.
- ///
- /// The alpha component value of this .
- /// The hue component value of this .
- /// The saturation component value of this .
- /// The value component value of this .
- /// The color created from the values.
- public static Color FromHSV(int a, double hue, double saturation, double value)
- {
- (byte r, byte g, byte b) = CalculateRGBFromHSV(hue, saturation, value);
- return new Color(a, r, g, b);
- }
-
- ///
- /// Creates a new instance of the struct using a HEX-string.
- ///
- /// The HEX-representation of the color.
- /// The color created from the HEX-string.
- public static Color FromHexString(string hexString)
- {
- if ((hexString == null) || (hexString.Length < 6))
- throw new ArgumentException("Invalid hex string", nameof(hexString));
-
- if (hexString[0] == '#')
- hexString = hexString.Substring(1);
-
- byte[] data = ConversionHelper.HexToBytes(hexString);
- if (data.Length == 3)
- return new Color(data[0], data[1], data[2]);
- if (data.Length == 4)
- return new Color(data[0], data[1], data[2], data[3]);
-
- throw new ArgumentException("Invalid hex string", nameof(hexString));
- }
-
- #endregion
-
- private static (double h, double s, double v) CaclulateHSVFromRGB(byte r, byte g, byte b)
- {
- if ((r == g) && (g == b)) return (0, 0, r / 255.0);
-
- int min = Math.Min(Math.Min(r, g), b);
- int max = Math.Max(Math.Max(r, g), b);
-
- double hue;
- if (max == min)
- hue = 0;
- else if (max == r) // r is max
- hue = (g - b) / (double)(max - min);
- else if (max == g) // g is max
- hue = 2.0 + ((b - r) / (double)(max - min));
- else // b is max
- hue = 4.0 + ((r - g) / (double)(max - min));
-
- hue = hue * 60.0;
- if (hue < 0.0)
- hue += 360.0;
-
- double saturation = (max == 0) ? 0 : 1.0 - (min / (double)max);
- double value = Math.Max(r, Math.Max(g, b)) / 255.0;
-
- return (hue, saturation, value);
- }
-
- private static (byte r, byte g, byte b) CalculateRGBFromHSV(double h, double s, double v)
- {
- h = h.Wrap(0, 360);
- s = s.Clamp(0, 1);
- v = v.Clamp(0, 1);
-
- if (s <= 0.0)
- {
- byte val = v.GetByteValueFromPercentage();
- return (val, val, val);
- }
-
- double hh = h / 60.0;
- int i = (int)hh;
- double ff = hh - i;
- double p = v * (1.0 - s);
- double q = v * (1.0 - (s * ff));
- double t = v * (1.0 - (s * (1.0 - ff)));
-
- switch (i)
- {
- case 0:
- return (v.GetByteValueFromPercentage(),
- t.GetByteValueFromPercentage(),
- p.GetByteValueFromPercentage());
- case 1:
- return (q.GetByteValueFromPercentage(),
- v.GetByteValueFromPercentage(),
- p.GetByteValueFromPercentage());
- case 2:
- return (p.GetByteValueFromPercentage(),
- v.GetByteValueFromPercentage(),
- t.GetByteValueFromPercentage());
- case 3:
- return (p.GetByteValueFromPercentage(),
- q.GetByteValueFromPercentage(),
- v.GetByteValueFromPercentage());
- case 4:
- return (t.GetByteValueFromPercentage(),
- p.GetByteValueFromPercentage(),
- v.GetByteValueFromPercentage());
- default:
- return (v.GetByteValueFromPercentage(),
- p.GetByteValueFromPercentage(),
- q.GetByteValueFromPercentage());
- }
- }
-
- ///
- /// Converts the individual byte values of this to a human-readable string.
- ///
- /// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]".
- public override string ToString() => $"[A: {A}, R: {R}, G: {G}, B: {B}, H: {Hue}, S: {Saturation}, V: {Value}]";
-
- ///
- /// Tests whether the specified object is a and is equivalent to this .
- ///
- /// The object to test.
- /// true if is a equivalent to this ; otherwise, false.
- public override bool Equals(object obj)
- {
- if (!(obj is Color)) return false;
-
- Color compareColor = (Color)obj;
- return (compareColor.A == A) && (compareColor.R == R) && (compareColor.G == G) && (compareColor.B == B);
- }
-
- ///
- /// Returns a hash code for this .
- ///
- /// An integer value that specifies the hash code for this .
- public override int GetHashCode()
- {
- unchecked
- {
- int hashCode = A.GetHashCode();
- hashCode = (hashCode * 397) ^ R.GetHashCode();
- hashCode = (hashCode * 397) ^ G.GetHashCode();
- hashCode = (hashCode * 397) ^ B.GetHashCode();
- return hashCode;
- }
- }
-
- ///
- /// Gets the current color as a RGB-HEX-string.
- ///
- /// The RGB-HEX-string.
- public string AsRGBHexString() => ConversionHelper.ToHex(R, G, B);
-
- ///
- /// Gets the current color as a ARGB-HEX-string.
- ///
- /// The ARGB-HEX-string.
- public string AsARGBHexString() => ConversionHelper.ToHex(A, R, G, B);
-
- #region Deconstruction
-
- ///
- /// Deconstructs the Color into it's components.
- ///
- /// The alpha component of this color.
- /// The red component of this color.
- /// The green component of this color.
- /// The blue component of this color.
- /// The hue component of this color.
- /// The saturation component of this color.
- /// The value component of this color.
- public void Deconstruct(out byte a, out byte r, out byte g, out byte b, out double hue, out double saturation, out double value)
- {
- Deconstruct(out a, out r, out g, out b);
- Deconstruct(out hue, out saturation, out value);
- }
-
- ///
- /// Deconstructs the Color into it's ARGB-components.
- ///
- /// The alpha component of this color.
- /// The red component of this color.
- /// The green component of this color.
- /// The blue component of this color.
- public void Deconstruct(out byte a, out byte r, out byte g, out byte b)
- {
- a = A;
- r = R;
- g = G;
- b = B;
- }
-
- ///
- /// Deconstructs the Color into it's HSV-components.
- ///
- /// The hue component of this color.
- /// The saturation component of this color.
- /// The value component of this color.
- public void Deconstruct(out double hue, out double saturation, out double value)
- {
- hue = Hue;
- saturation = Saturation;
- value = Value;
- }
-
- #endregion
-
- #region Manipulation
-
- ///
- /// Blends a over this color.
- ///
- /// The to blend.
- public Color Blend(Color color)
- {
- if (color.A == 0) return this;
-
- if (color.A == 255)
- return color;
-
- double resultA = (1.0 - ((1.0 - color.APercent) * (1.0 - APercent)));
- double resultR = (((color.RPercent * color.APercent) / resultA) + ((RPercent * APercent * (1.0 - color.APercent)) / resultA));
- double resultG = (((color.GPercent * color.APercent) / resultA) + ((GPercent * APercent * (1.0 - color.APercent)) / resultA));
- double resultB = (((color.BPercent * color.APercent) / resultA) + ((BPercent * APercent * (1.0 - color.APercent)) / resultA));
-
- return new Color(resultA, resultR, resultG, resultB);
- }
-
- #region Add
-
- ///
- /// Adds the given RGB values to this color.
- ///
- /// The red value to add.
- /// The green value to add.
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddRGB(int r, int g, int b) => AddRGB(0, r, g, b);
-
- ///
- /// Adds the given RGB values to this color.
- ///
- /// The alpha value to add.
- /// The red value to add.
- /// The green value to add.
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddRGB(int a, int r, int g, int b)
- => new Color(A + a, R + r, G + g, B + b);
-
- ///
- /// Adds the given RGB-percent values to this color.
- ///
- /// The red value to add.
- /// The green value to add.
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddPercent(double rPercent, double gPercent, double bPercent) => AddPercent(0, rPercent, gPercent, bPercent);
-
- ///
- /// Adds the given RGB-percent values to this color.
- ///
- /// The alpha value to add.
- /// The red value to add.
- /// The green value to add.
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddPercent(double aPercent, double rPercent, double gPercent, double bPercent)
- => new Color(APercent + aPercent, RPercent + rPercent, GPercent + gPercent, BPercent + bPercent);
-
- ///
- /// Adds the given HSV values to this color.
- ///
- /// The hue value to add.
- /// The saturation value to add.
- /// The value value to add.
- /// The new color after the modification.
- public Color AddHSV(double hue, double saturation, double value) => AddHSV(0, hue, saturation, value);
-
- ///
- /// Adds the given HSV values to this color.
- ///
- /// The alpha value to add.
- /// The hue value to add.
- /// The saturation value to add.
- /// The value value to add.
- /// The new color after the modification.
- public Color AddHSV(int a, double hue, double saturation, double value)
- => FromHSV(A + a, Hue + hue, Saturation + saturation, Value + value);
-
- ///
- /// Adds the given alpha value to this color.
- ///
- /// The alpha value to add.
- /// The new color after the modification.
- public Color AddA(int a) => new Color(A + a, R, G, B);
-
- ///
- /// Adds the given alpha-percent value to this color.
- ///
- /// The alpha value to add.
- /// The new color after the modification.
- public Color AddAPercent(double aPercent) => new Color(APercent + aPercent, RPercent, GPercent, BPercent);
-
- ///
- /// Adds the given red value to this color.
- ///
- /// The red value to add.
- /// The new color after the modification.
- public Color AddR(int r) => new Color(A, R + r, G, B);
-
- ///
- /// Adds the given red-percent value to this color.
- ///
- /// The red value to add.
- /// The new color after the modification.
- public Color AddRPercent(double rPercent) => new Color(APercent, RPercent + rPercent, GPercent, BPercent);
-
- ///
- /// Adds the given green value to this color.
- ///
- /// The green value to add.
- /// The new color after the modification.
- public Color AddG(int g) => new Color(A, R, G + g, B);
-
- ///
- /// Adds the given green-percent value to this color.
- ///
- /// The green value to add.
- /// The new color after the modification.
- public Color AddGPercent(double gPercent) => new Color(APercent, RPercent, GPercent + gPercent, BPercent);
-
- ///
- /// Adds the given blue value to this color.
- ///
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddB(int b) => new Color(A, R, G, B + b);
-
- ///
- /// Adds the given blue-percent value to this color.
- ///
- /// The blue value to add.
- /// The new color after the modification.
- public Color AddBPercent(double bPercent) => new Color(APercent, RPercent, GPercent, BPercent + bPercent);
-
- ///
- /// Adds the given hue value to this color.
- ///
- /// The hue value to add.
- /// The new color after the modification.
- public Color AddHue(double hue) => FromHSV(A, Hue + hue, Saturation, Value);
-
- ///
- /// Adds the given saturation value to this color.
- ///
- /// The saturation value to add.
- /// The new color after the modification.
- public Color AddSaturation(double saturation) => FromHSV(A, Hue, Saturation + saturation, Value);
-
- ///
- /// Adds the given value value to this color.
- ///
- /// The value value to add.
- /// The new color after the modification.
- public Color AddValue(double value) => FromHSV(A, Hue, Saturation, Value + value);
-
- #endregion
-
- #region Subtract
-
- ///
- /// Subtracts the given RGB values to this color.
- ///
- /// The red value to subtract.
- /// The green value to subtract.
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractRGB(int r, int g, int b) => SubtractRGB(0, r, g, b);
-
- ///
- /// Subtracts the given RGB values to this color.
- ///
- /// The alpha value to subtract.
- /// The red value to subtract.
- /// The green value to subtract.
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractRGB(int a, int r, int g, int b)
- => new Color(A - a, R - r, G - g, B - b);
-
- ///
- /// Subtracts the given RGB-percent values to this color.
- ///
- /// The red value to subtract.
- /// The green value to subtract.
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractPercent(double rPercent, double gPercent, double bPercent) => SubtractPercent(0, rPercent, gPercent, bPercent);
-
- ///
- /// Subtracts the given RGB-percent values to this color.
- ///
- /// The alpha value to subtract.
- /// The red value to subtract.
- /// The green value to subtract.
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractPercent(double aPercent, double rPercent, double gPercent, double bPercent)
- => new Color(APercent - aPercent, RPercent - rPercent, GPercent - gPercent, BPercent - bPercent);
-
- ///
- /// Subtracts the given HSV values to this color.
- ///
- /// The hue value to subtract.
- /// The saturation value to subtract.
- /// The value value to subtract.
- /// The new color after the modification.
- public Color SubtractHSV(double hue, double saturation, double value) => SubtractHSV(0, hue, saturation, value);
-
- ///
- /// Subtracts the given HSV values to this color.
- ///
- /// The alpha value to subtract.
- /// The hue value to subtract.
- /// The saturation value to subtract.
- /// The value value to subtract.
- /// The new color after the modification.
- public Color SubtractHSV(int a, double hue, double saturation, double value)
- => FromHSV(A - a, Hue - hue, Saturation - saturation, Value - value);
-
- ///
- /// Subtracts the given alpha value to this color.
- ///
- /// The alpha value to subtract.
- /// The new color after the modification.
- public Color SubtractA(int a) => new Color(A - a, R, G, B);
-
- ///
- /// Subtracts the given alpha-percent value to this color.
- ///
- /// The alpha value to subtract.
- /// The new color after the modification.
- public Color SubtractAPercent(double aPercent) => new Color(APercent - aPercent, RPercent, GPercent, BPercent);
-
- ///
- /// Subtracts the given red value to this color.
- ///
- /// The red value to subtract.
- /// The new color after the modification.
- public Color SubtractR(int r) => new Color(A, R - r, G, B);
-
- ///
- /// Subtracts the given red-percent value to this color.
- ///
- /// The red value to subtract.
- /// The new color after the modification.
- public Color SubtractRPercent(double rPercent) => new Color(APercent, RPercent - rPercent, GPercent, BPercent);
-
- ///
- /// Subtracts the given green value to this color.
- ///
- /// The green value to subtract.
- /// The new color after the modification.
- public Color SubtractG(int g) => new Color(A, R, G - g, B);
-
- ///
- /// Subtracts the given green-percent value to this color.
- ///
- /// The green value to subtract.
- /// The new color after the modification.
- public Color SubtractGPercent(double gPercent) => new Color(APercent, RPercent, GPercent - gPercent, BPercent);
-
- ///
- /// Subtracts the given blue value to this color.
- ///
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractB(int b) => new Color(A, R, G, B - b);
-
- ///
- /// Subtracts the given blue-percent value to this color.
- ///
- /// The blue value to subtract.
- /// The new color after the modification.
- public Color SubtractBPercent(double bPercent) => new Color(APercent, RPercent, GPercent, BPercent - bPercent);
-
- ///
- /// Subtracts the given hue value to this color.
- ///
- /// The hue value to subtract.
- /// The new color after the modification.
- public Color SubtractHue(double hue) => FromHSV(A, Hue - hue, Saturation, Value);
-
- ///
- /// Subtracts the given saturation value to this color.
- ///
- /// The saturation value to subtract.
- /// The new color after the modification.
- public Color SubtractSaturation(double saturation) => FromHSV(A, Hue, Saturation - saturation, Value);
-
- ///
- /// Subtracts the given value value to this color.
- ///
- /// The value value to subtract.
- /// The new color after the modification.
- public Color SubtractValue(double value) => FromHSV(A, Hue, Saturation, Value - value);
-
- #endregion
-
- #region Multiply
-
- ///
- /// Multiplies the given RGB values to this color.
- ///
- /// The red value to multiply.
- /// The green value to multiply.
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyRGB(double r, double g, double b) => MultiplyRGB(1, r, g, b);
-
- ///
- /// Multiplies the given RGB values to this color.
- ///
- /// The alpha value to multiply.
- /// The red value to multiply.
- /// The green value to multiply.
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyRGB(double a, double r, double g, double b)
- => new Color((int)Math.Round(A * a), (int)Math.Round(R * r), (int)Math.Round(G * g), (int)Math.Round(B * b));
-
- ///
- /// Multiplies the given RGB-percent values to this color.
- ///
- /// The red value to multiply.
- /// The green value to multiply.
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyPercent(double rPercent, double gPercent, double bPercent) => MultiplyPercent(1, rPercent, gPercent, bPercent);
-
- ///
- /// Multiplies the given RGB-percent values to this color.
- ///
- /// The alpha value to multiply.
- /// The red value to multiply.
- /// The green value to multiply.
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyPercent(double aPercent, double rPercent, double gPercent, double bPercent)
- => new Color(APercent * aPercent, RPercent * rPercent, GPercent * gPercent, BPercent * bPercent);
-
- ///
- /// Multiplies the given HSV values to this color.
- ///
- /// The hue value to multiply.
- /// The saturation value to multiply.
- /// The value value to multiply.
- /// The new color after the modification.
- public Color MultiplyHSV(double hue, double saturation, double value) => MultiplyHSV(1, hue, saturation, value);
-
- ///
- /// Multiplies the given HSV values to this color.
- ///
- /// The alpha value to multiply.
- /// The hue value to multiply.
- /// The saturation value to multiply.
- /// The value value to multiply.
- /// The new color after the modification.
- public Color MultiplyHSV(double a, double hue, double saturation, double value)
- => FromHSV((int)Math.Round(A * a), Hue * hue, Saturation * saturation, Value * value);
-
- ///
- /// Multiplies the given alpha value to this color.
- ///
- /// The alpha value to multiply.
- /// The new color after the modification.
- public Color MultiplyA(double a) => new Color((int)Math.Round(A * a), R, G, B);
-
- ///
- /// Multiplies the given alpha-percent value to this color.
- ///
- /// The alpha value to multiply.
- /// The new color after the modification.
- public Color MultiplyAPercent(double aPercent) => new Color(APercent * aPercent, RPercent, GPercent, BPercent);
-
- ///
- /// Multiplies the given red value to this color.
- ///
- /// The red value to multiply.
- /// The new color after the modification.
- public Color MultiplyR(double r) => new Color(A, (int)Math.Round(R * r), G, B);
-
- ///
- /// Multiplies the given red-percent value to this color.
- ///
- /// The red value to multiply.
- /// The new color after the modification.
- public Color MultiplyRPercent(double rPercent) => new Color(APercent, RPercent * rPercent, GPercent, BPercent);
-
- ///
- /// Multiplies the given green value to this color.
- ///
- /// The green value to multiply.
- /// The new color after the modification.
- public Color MultiplyG(double g) => new Color(A, R, (int)Math.Round(G * g), B);
-
- ///
- /// Multiplies the given green-percent value to this color.
- ///
- /// The green value to multiply.
- /// The new color after the modification.
- public Color MultiplyGPercent(double gPercent) => new Color(APercent, RPercent, GPercent * gPercent, BPercent);
-
- ///
- /// Multiplies the given blue value to this color.
- ///
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyB(double b) => new Color(A, R, G, (int)Math.Round(B * b));
-
- ///
- /// Multiplies the given blue-percent value to this color.
- ///
- /// The blue value to multiply.
- /// The new color after the modification.
- public Color MultiplyBPercent(double bPercent) => new Color(APercent, RPercent, GPercent, BPercent * bPercent);
-
- ///
- /// Multiplies the given hue value to this color.
- ///
- /// The hue value to multiply.
- /// The new color after the modification.
- public Color MultiplyHue(double hue) => FromHSV(A, Hue * hue, Saturation, Value);
-
- ///
- /// Multiplies the given saturation value to this color.
- ///
- /// The saturation value to multiply.
- /// The new color after the modification.
- public Color MultiplySaturation(double saturation) => FromHSV(A, Hue, Saturation * saturation, Value);
-
- ///
- /// Multiplies the given value value to this color.
- ///
- /// The value value to multiply.
- /// The new color after the modification.
- public Color MultiplyValue(double value) => FromHSV(A, Hue, Saturation, Value * value);
-
- #endregion
-
- #region Divide
-
- ///
- /// Divides the given RGB values to this color.
- ///
- /// The red value to divide.
- /// The green value to divide.
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DivideRGB(double r, double g, double b) => DivideRGB(1, r, g, b);
-
- ///
- /// Divides the given RGB values to this color.
- ///
- /// The alpha value to divide.
- /// The red value to divide.
- /// The green value to divide.
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DivideRGB(double a, double r, double g, double b)
- => new Color((int)Math.Round(A / a), (int)Math.Round(R / r), (int)Math.Round(G / g), (int)Math.Round(B / b));
-
- ///
- /// Divides the given RGB-percent values to this color.
- ///
- /// The red value to divide.
- /// The green value to divide.
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DividePercent(double rPercent, double gPercent, double bPercent) => DividePercent(1, rPercent, gPercent, bPercent);
-
- ///
- /// Divides the given RGB-percent values to this color.
- ///
- /// The alpha value to divide.
- /// The red value to divide.
- /// The green value to divide.
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DividePercent(double aPercent, double rPercent, double gPercent, double bPercent)
- => new Color(APercent / aPercent, RPercent / rPercent, GPercent / gPercent, BPercent / bPercent);
-
- ///
- /// Divides the given HSV values to this color.
- ///
- /// The hue value to divide.
- /// The saturation value to divide.
- /// The value value to divide.
- /// The new color after the modification.
- public Color DivideHSV(double hue, double saturation, double value) => DivideHSV(1, hue, saturation, value);
-
- ///
- /// Divides the given HSV values to this color.
- ///
- /// The alpha value to divide.
- /// The hue value to divide.
- /// The saturation value to divide.
- /// The value value to divide.
- /// The new color after the modification.
- public Color DivideHSV(double a, double hue, double saturation, double value)
- => FromHSV((int)Math.Round(A / a), Hue / hue, Saturation / saturation, Value / value);
-
- ///
- /// Divides the given alpha value to this color.
- ///
- /// The alpha value to divide.
- /// The new color after the modification.
- public Color DivideA(double a) => new Color((int)Math.Round(A / a), R, G, B);
-
- ///
- /// Divides the given alpha-percent value to this color.
- ///
- /// The alpha value to divide.
- /// The new color after the modification.
- public Color DivideAPercent(double aPercent) => new Color(APercent / aPercent, RPercent, GPercent, BPercent);
-
- ///
- /// Divides the given red value to this color.
- ///
- /// The red value to divide.
- /// The new color after the modification.
- public Color DivideRValue(double r) => new Color(A, (int)Math.Round(R / r), G, B);
-
- ///
- /// Divides the given red-percent value to this color.
- ///
- /// The red value to divide.
- /// The new color after the modification.
- public Color DivideRPercent(double rPercent) => new Color(APercent, RPercent / rPercent, GPercent, BPercent);
-
- ///
- /// Divides the given green value to this color.
- ///
- /// The green value to divide.
- /// The new color after the modification.
- public Color DivideGValue(double g) => new Color(A, R, (int)Math.Round(G / g), B);
-
- ///
- /// Divides the given green-percent value to this color.
- ///
- /// The green value to divide.
- /// The new color after the modification.
- public Color DivideGPercent(double gPercent) => new Color(APercent, RPercent, GPercent / gPercent, BPercent);
-
- ///
- /// Divides the given blue value to this color.
- ///
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DivideBValue(double b) => new Color(A, R, G, (int)Math.Round(B / b));
-
- ///
- /// Divides the given blue-percent value to this color.
- ///
- /// The blue value to divide.
- /// The new color after the modification.
- public Color DivideBPercent(double bPercent) => new Color(APercent, RPercent, GPercent, BPercent / bPercent);
-
- ///
- /// Divides the given hue value to this color.
- ///
- /// The hue value to divide.
- /// The new color after the modification.
- public Color DivideHue(double hue) => FromHSV(A, Hue / hue, Saturation, Value);
-
- ///
- /// Divides the given saturation value to this color.
- ///
- /// The saturation value to divide.
- /// The new color after the modification.
- public Color DivideSaturation(double saturation) => FromHSV(A, Hue, Saturation / saturation, Value);
-
- ///
- /// Divides the given value value to this color.
- ///
- /// The value value to divide.
- /// The new color after the modification.
- public Color DivideValue(double value) => FromHSV(A, Hue, Saturation, Value / value);
-
- #endregion
-
- #region Set
-
- ///
- /// Sets the given alpha value of this color.
- ///
- /// The alpha value to set.
- /// The new color after the modification.
- public Color SetA(int a) => new Color(a, R, G, B);
-
- ///
- /// Sets the given alpha-percent value of this color.
- ///
- /// The alpha value to set.
- /// The new color after the modification.
- public Color SetAPercent(double aPercent) => new Color(aPercent, RPercent, GPercent, BPercent);
-
- ///
- /// Sets the given red value of this color.
- ///
- /// The red value to set.
- /// The new color after the modification.
- public Color SetR(int r) => new Color(A, r, G, B);
-
- ///
- /// Sets the given red-percent value of this color.
- ///
- /// The red value to set.
- /// The new color after the modification.
- public Color SetRPercent(double rPercent) => new Color(APercent, rPercent, GPercent, BPercent);
-
- ///
- /// Sets the given green value of this color.
- ///
- /// The green value to set.
- /// The new color after the modification.
- public Color SetG(int g) => new Color(A, R, g, B);
-
- ///
- /// Sets the given green-percent value of this color.
- ///
- /// The green value to set.
- /// The new color after the modification.
- public Color SetGPercent(double gPercent) => new Color(APercent, RPercent, gPercent, BPercent);
-
- ///
- /// Sets the given blue value of this color.
- ///
- /// The blue value to set.
- /// The new color after the modification.
- public Color SetB(int b) => new Color(A, R, G, b);
-
- ///
- /// Sets the given blue-percent value of this color.
- ///
- /// The blue value to set.
- /// The new color after the modification.
- public Color SetBPercent(double bPercent) => new Color(APercent, RPercent, GPercent, bPercent);
-
- ///
- /// Sets the given hue value of this color.
- ///
- /// The hue value to set.
- /// The new color after the modification.
- public Color SetHue(double hue) => FromHSV(A, hue, Saturation, Value);
-
- ///
- /// Sets the given saturation value of this color.
- ///
- /// The saturation value to set.
- /// The new color after the modification.
- public Color SetSaturation(double saturation) => FromHSV(A, Hue, saturation, Value);
-
- ///
- /// Sets the given value value of this color.
- ///
- /// The value value to set.
- /// The new color after the modification.
- public Color SetValue(double value) => FromHSV(A, Hue, Saturation, value);
-
- #endregion
-
- #endregion
-
- #endregion
-
- #region Operators
-
- ///
- /// Blends the provided colors as if would've been called on .
- ///
- /// The base color.
- /// The color to blend.
- /// The blended color.
- public static Color operator +(Color color1, Color color2) => color1.Blend(color2);
-
- ///
- /// Returns a value that indicates whether two specified are equal.
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if and are equal; otherwise, false.
- public static bool operator ==(Color color1, Color color2) => color1.Equals(color2);
-
- ///
- /// Returns a value that indicates whether two specified are equal.
- ///
- /// The first to compare.
- /// The second to compare.
- /// true if and are not equal; otherwise, false.
- public static bool operator !=(Color color1, Color color2) => !(color1 == color2);
-
- ///
- /// Converts a of ARGB-components to a .
- ///
- /// The containing the components.
- /// The color.
- public static implicit operator Color((byte a, byte r, byte g, byte b) components) => new Color(components.a, components.r, components.g, components.b);
-
- ///
- /// Converts a of HSV-components to a .
- ///
- /// The containing the components.
- /// The color.
- public static implicit operator Color((double hue, double saturation, double value) components) => new Color(components.hue, components.saturation, components.value);
-
- #endregion
- }
-}
diff --git a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
index d88c562..739bd7f 100644
--- a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
+++ b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
@@ -1,5 +1,6 @@
True
+ TrueTrueTrueTrue
diff --git a/RGB.NET.Decorators/Brush/FlashDecorator.cs b/RGB.NET.Decorators/Brush/FlashDecorator.cs
index dd84f2c..618b243 100644
--- a/RGB.NET.Decorators/Brush/FlashDecorator.cs
+++ b/RGB.NET.Decorators/Brush/FlashDecorator.cs
@@ -77,7 +77,7 @@ namespace RGB.NET.Decorators.Brush
#region Methods
///
- public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetAPercent(_currentValue);
+ public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetA(_currentValue);
///
protected override void Update(double deltaTime)
diff --git a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs
index 65460e2..a3570c9 100644
--- a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs
+++ b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs
@@ -40,14 +40,16 @@ namespace RGB.NET.Devices.Novation
/// The novation-representation of the .
protected virtual int ConvertColor(Color color)
{
- if ((color.Hue >= 330) || (color.Hue < 30))
- return (int)Math.Ceiling(color.Value * 3); // red with brightness 1, 2 or 3
+ (double hue, double saturation, double value) = color.GetHSV();
- if ((color.Hue >= 30) && (color.Hue < 90)) // yellow with brightness 17, 34 or 51
- return (int)Math.Ceiling(color.Value * 3) * 17;
+ if ((hue >= 330) || (hue < 30))
+ return (int)Math.Ceiling(value * 3); // red with brightness 1, 2 or 3
- if ((color.Hue >= 90) && (color.Hue < 150)) // green with brightness 16, 32 or 48
- return (int)Math.Ceiling(color.Value * 3) * 16;
+ if ((hue >= 30) && (hue < 90)) // yellow with brightness 17, 34 or 51
+ return (int)Math.Ceiling(value * 3) * 17;
+
+ if ((hue >= 90) && (hue < 150)) // green with brightness 16, 32 or 48
+ return (int)Math.Ceiling(value * 3) * 16;
return 0;
}
diff --git a/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs
index 0ba9697..c3bec0f 100644
--- a/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs
+++ b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs
@@ -66,7 +66,7 @@ namespace RGB.NET.Devices.SoIP.Client
List<(LedId, Color)> leds = message.MessageString.Split(';').Select(x =>
{
string[] led = x.Split('|');
- return ((LedId)Enum.Parse(typeof(LedId), led[0]), Color.FromHexString(led[1]));
+ return ((LedId)Enum.Parse(typeof(LedId), led[0]), RGBColor.FromHexString(led[1]));
}).ToList();
lock (_syncbackCache)
foreach ((LedId ledId, Color color) in leds)
diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs
index 79c20a1..5a5285e 100644
--- a/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs
+++ b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs
@@ -61,7 +61,7 @@ namespace RGB.NET.Devices.SoIP.Server
tcpClient.GetStream().WriteAsync(messageData, 0, messageData.Length);
}
- private string GetLedString(IEnumerable leds) => string.Join(";", leds.Select(x => x.Id.ToString() + "|" + x.Color.AsARGBHexString()));
+ private string GetLedString(IEnumerable leds) => string.Join(";", leds.Select(x => x.Id.ToString() + "|" + x.Color.AsARGBHexString(false)));
///
public override void Dispose()
diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs
index 999ef9c..1d100ce 100644
--- a/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs
+++ b/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs
@@ -46,7 +46,7 @@ namespace RGB.NET.Devices.SoIP.Server
}
}
- private string GetLedString(Dictionary