diff --git a/RGB.NET.Brushes/Brushes/SolidColorBrush.cs b/RGB.NET.Brushes/Brushes/SolidColorBrush.cs index 6373d61..8e4a1a1 100644 --- a/RGB.NET.Brushes/Brushes/SolidColorBrush.cs +++ b/RGB.NET.Brushes/Brushes/SolidColorBrush.cs @@ -37,10 +37,7 @@ namespace RGB.NET.Brushes #region Methods /// - protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) - { - return Color; - } + protected override Color GetColorAtPoint(Rectangle rectangle, BrushRenderTarget renderTarget) => Color; #endregion @@ -50,19 +47,13 @@ namespace RGB.NET.Brushes /// Converts a to a . /// /// The to convert. - public static explicit operator SolidColorBrush(Color color) - { - return new SolidColorBrush(color); - } + public static explicit operator SolidColorBrush(Color color) => new SolidColorBrush(color); /// /// Converts a to a . /// /// The to convert. - public static implicit operator Color(SolidColorBrush brush) - { - return brush.Color; - } + public static implicit operator Color(SolidColorBrush brush) => brush.Color; #endregion } diff --git a/RGB.NET.Brushes/Gradients/LinearGradient.cs b/RGB.NET.Brushes/Gradients/LinearGradient.cs index 0b1dc38..8732262 100644 --- a/RGB.NET.Brushes/Gradients/LinearGradient.cs +++ b/RGB.NET.Brushes/Gradients/LinearGradient.cs @@ -53,7 +53,7 @@ namespace RGB.NET.Brushes.Gradients public override Color GetColor(double offset) { if (GradientStops.Count == 0) return Color.Transparent; - if (GradientStops.Count == 1) return new Color(GradientStops[0].Color); + if (GradientStops.Count == 1) return GradientStops[0].Color; (GradientStop gsBefore, GradientStop gsAfter) = GetEnclosingGradientStops(offset, GradientStops, WrapGradient); diff --git a/RGB.NET.Brushes/Gradients/RainbowGradient.cs b/RGB.NET.Brushes/Gradients/RainbowGradient.cs index 0df739b..e565b24 100644 --- a/RGB.NET.Brushes/Gradients/RainbowGradient.cs +++ b/RGB.NET.Brushes/Gradients/RainbowGradient.cs @@ -56,7 +56,7 @@ namespace RGB.NET.Brushes.Gradients double hue = (StartHue + (range * offset)) % 360f; if (hue < 0) hue += 360; - return new Color(hue, 1f, 1f); + return Color.FromHSV(hue, 1, 1); } /// diff --git a/RGB.NET.Core/Brushes/AbstractBrush.cs b/RGB.NET.Core/Brushes/AbstractBrush.cs index 0193913..716cc4a 100644 --- a/RGB.NET.Core/Brushes/AbstractBrush.cs +++ b/RGB.NET.Core/Brushes/AbstractBrush.cs @@ -64,8 +64,8 @@ namespace RGB.NET.Core foreach (BrushRenderTarget renderTarget in renderTargets) { - Color color = new Color(GetColorAtPoint(rectangle, renderTarget)); // Clone the color, we don't want to have reference issues here and brushes might return the same color multiple times!} - ApplyDecorators(rectangle, renderTarget, ref color); + Color color = GetColorAtPoint(rectangle, renderTarget); + color = ApplyDecorators(rectangle, renderTarget, color); RenderedTargets[renderTarget] = color; } } @@ -76,11 +76,13 @@ namespace RGB.NET.Core /// The rectangle in which the brush should be drawn. /// The target (key/point) from which the color should be taken. /// The to be modified. - protected virtual void ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color) + protected virtual Color ApplyDecorators(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) { foreach (IBrushDecorator decorator in Decorators) if (decorator.IsEnabled) - decorator.ManipulateColor(rectangle, renderTarget, ref color); + color = decorator.ManipulateColor(rectangle, renderTarget, color); + + return color; } /// @@ -88,7 +90,7 @@ namespace RGB.NET.Core { List renderTargets = RenderedTargets.Keys.ToList(); foreach (BrushRenderTarget renderTarget in renderTargets) - FinalizeColor(RenderedTargets[renderTarget]); // Cloning here again shouldn't be needed since we did this above. + RenderedTargets[renderTarget] = FinalizeColor(RenderedTargets[renderTarget]); } /// @@ -102,20 +104,19 @@ namespace RGB.NET.Core /// /// Finalizes the color by appliing the overall brightness and opacity.
/// This method should always be the last call of a implementation. - /// If you overwrite this method please make sure that you never return the same color-object twice to prevent reference-issues! ///
/// The color to finalize. /// The finalized color. - protected virtual void FinalizeColor(Color color) + protected virtual Color FinalizeColor(Color color) { foreach (IColorCorrection colorCorrection in ColorCorrections) - colorCorrection.ApplyTo(color); + color = colorCorrection.ApplyTo(color); // 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!!! - color.Value *= Brightness <= 0 ? 0 : (Brightness >= 1.0 ? 1.0 : Brightness); - color.A = (byte)(color.A * (Opacity <= 0 ? 0 : (Opacity >= 1.0 ? 1.0 : Opacity))); + return color.MultiplyValue(Brightness.Clamp(0, 1)) + .MultiplyA(Opacity.Clamp(0, 1)); } #endregion diff --git a/RGB.NET.Core/ColorCorrection/IColorCorrection.cs b/RGB.NET.Core/ColorCorrection/IColorCorrection.cs index 034ac9f..e3e417a 100644 --- a/RGB.NET.Core/ColorCorrection/IColorCorrection.cs +++ b/RGB.NET.Core/ColorCorrection/IColorCorrection.cs @@ -11,6 +11,6 @@ namespace RGB.NET.Core /// Applies the to the given . ///
/// The to correct. - void ApplyTo(Color color); + Color ApplyTo(Color color); } } diff --git a/RGB.NET.Core/Decorators/IBrushDecorator.cs b/RGB.NET.Core/Decorators/IBrushDecorator.cs index aef4f2c..812af24 100644 --- a/RGB.NET.Core/Decorators/IBrushDecorator.cs +++ b/RGB.NET.Core/Decorators/IBrushDecorator.cs @@ -12,6 +12,6 @@ /// The rectangle in which the should be drawn. /// The target (key/point) from which the should be taken. /// The to be modified. - void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color); + Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color); } } diff --git a/RGB.NET.Core/Extensions/DoubleExtensions.cs b/RGB.NET.Core/Extensions/DoubleExtensions.cs deleted file mode 100644 index 964a205..0000000 --- a/RGB.NET.Core/Extensions/DoubleExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace RGB.NET.Core -{ - /// - /// Offers some extensions and helper-methods for the work with doubles - /// - public static class DoubleExtensions - { - #region Constants - - /// - /// Defines the precision RGB.NET processes floating point comparisons in. - /// - public const double TOLERANCE = 1E-10; - - #endregion - - #region Methods - - /// - /// Checks if two values are equal respecting the . - /// - /// The first value to compare. - /// The first value to compare. - /// true if the difference is smaller than the ; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool EqualsInTolerance(this double value1, double value2) - { - return Math.Abs(value1 - value2) < TOLERANCE; - } - - /// - /// Camps the provided value to be bigger or equal min and smaller or equal max. - /// - /// The value to clamp. - /// The lower value of the range the value is clamped to. - /// The higher value of the range the value is clamped to. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Clamp(this double value, double min, double max) - { - return Math.Max(min, Math.Min(max, value)); - } - - #endregion - } -} diff --git a/RGB.NET.Core/Extensions/MathExtensions.cs b/RGB.NET.Core/Extensions/MathExtensions.cs new file mode 100644 index 0000000..34b92d8 --- /dev/null +++ b/RGB.NET.Core/Extensions/MathExtensions.cs @@ -0,0 +1,87 @@ +using System; +using System.Runtime.CompilerServices; + +namespace RGB.NET.Core +{ + /// + /// Offers some extensions and helper-methods for the work with doubles + /// + public static class DoubleExtensions + { + #region Constants + + /// + /// Defines the precision RGB.NET processes floating point comparisons in. + /// + public const double TOLERANCE = 1E-10; + + #endregion + + #region Methods + + /// + /// Checks if two values are equal respecting the . + /// + /// The first value to compare. + /// The first value to compare. + /// true if the difference is smaller than the ; otherwise, false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsInTolerance(this double value1, double value2) => Math.Abs(value1 - value2) < TOLERANCE; + + /// + /// Clamps the provided value to be bigger or equal min and smaller or equal max. + /// + /// The value to clamp. + /// The lower value of the range the value is clamped to. + /// 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)); + + /// + /// Clamps the provided value to be bigger or equal min and smaller or equal max. + /// + /// The value to clamp. + /// The lower value of the range the value is clamped to. + /// 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)); + + /// + /// Enforces the provided value to be in the specified range by wrapping it around the edges if it exceeds them. + /// + /// The value to wrap. + /// The lower value of the range the value is wrapped into. + /// The higher value of the range the value is wrapped into. + /// The wrapped value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Wrap(this double value, double min, double max) + { + double range = max - min; + + while (value > max) + value -= range; + + while (value < min) + value += range; + + return value; + } + + #region Internal + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static byte GetByteValueFromPercentage(this double percentage) + { + if (double.IsNaN(percentage)) return 0; + + percentage = percentage.Clamp(0, 1.0); + return (byte)(percentage.Equals(1.0) ? 255 : percentage * 256.0); + } + + #endregion + + #endregion + } +} diff --git a/RGB.NET.Core/Leds/Color.cs b/RGB.NET.Core/Leds/Color.cs index c7391ac..65786b0 100644 --- a/RGB.NET.Core/Leds/Color.cs +++ b/RGB.NET.Core/Leds/Color.cs @@ -1,5 +1,6 @@ // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Global using System; using System.Diagnostics; @@ -11,14 +12,14 @@ 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 class Color : AbstractBindable + public struct Color { #region Constants /// /// Gets an transparent color [A: 0, R: 0, G: 0, B: 0] /// - public static Color Transparent => new Color(); + public static Color Transparent => new Color(0, 0, 0, 0); #endregion @@ -26,158 +27,64 @@ namespace RGB.NET.Core #region RGB - private byte _a; /// - /// Gets or sets the alpha component value of this as byte in the range [0..255]. + /// Gets the alpha component value of this as byte in the range [0..255]. /// - public byte A - { - get => _a; - set - { - if (SetProperty(ref _a, value)) - // ReSharper disable once ExplicitCallerInfoArgument - OnPropertyChanged(nameof(APercent)); - } - } + public byte A { get; } /// - /// Gets or sets the alpha component value of this as percentage in the range [0..1]. + /// Gets the alpha component value of this as percentage in the range [0..1]. /// - public double APercent - { - get => A / (double)byte.MaxValue; - set => A = GetByteValueFromPercentage(value); - } - - private byte _r; - /// - /// Gets or sets the red component value of this as byte in the range [0..255]. - /// - public byte R - { - get => _r; - set - { - if (SetProperty(ref _r, value)) - { - InvalidateHSV(); - // ReSharper disable once ExplicitCallerInfoArgument - OnPropertyChanged(nameof(RPercent)); - } - } - } + public double APercent => A / (double)byte.MaxValue; /// - /// Gets or sets the red component value of this as percentage in the range [0..1]. + /// Gets the red component value of this as byte in the range [0..255]. /// - public double RPercent - { - get => R / (double)byte.MaxValue; - set => R = GetByteValueFromPercentage(value); - } - - private byte _g; - /// - /// Gets or sets the green component value of this as byte in the range [0..255]. - /// - public byte G - { - get => _g; - set - { - if (SetProperty(ref _g, value)) - { - InvalidateHSV(); - // ReSharper disable ExplicitCallerInfoArgument - OnPropertyChanged(nameof(GPercent)); - // ReSharper restore ExplicitCallerInfoArgument - } - } - } + public byte R { get; } /// - /// Gets or sets the green component value of this as percentage in the range [0..1]. + /// Gets the red component value of this as percentage in the range [0..1]. /// - public double GPercent - { - get => G / (double)byte.MaxValue; - set => G = GetByteValueFromPercentage(value); - } - - private byte _b; - /// - /// Gets or sets the blue component value of this as byte in the range [0..255]. - /// - public byte B - { - get => _b; - set - { - if (SetProperty(ref _b, value)) - { - InvalidateHSV(); - // ReSharper disable ExplicitCallerInfoArgument - OnPropertyChanged(nameof(BPercent)); - // ReSharper restore ExplicitCallerInfoArgument - } - } - } + public double RPercent => R / (double)byte.MaxValue; /// - /// Gets or sets the blue component value of this as percentage in the range [0..1]. + /// Gets the green component value of this as byte in the range [0..255]. /// - public double BPercent - { - get => B / (double)byte.MaxValue; - set => B = GetByteValueFromPercentage(value); - } + 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 - private double? _hue; /// - /// Gets or sets the hue component value (HSV-color space) of this as degree in the range [0..360]. + /// Gets the hue component value (HSV-color space) of this as degree in the range [0..360]. /// - public double Hue - { - get => _hue ?? (_hue = CaclulateHueFromRGB()).Value; - set - { - if (SetProperty(ref _hue, value)) - UpdateRGBFromHSV(); - } - } + public double Hue { get; } - private double? _saturation; /// - /// Gets or sets the saturation component value (HSV-color space) of this as degree in the range [0..1]. + /// Gets the saturation component value (HSV-color space) of this as degree in the range [0..1]. /// - public double Saturation - { - get => _saturation ?? (_saturation = CaclulateSaturationFromRGB()).Value; - set - { - if (SetProperty(ref _saturation, value)) - UpdateRGBFromHSV(); - } - } + public double Saturation { get; } - private double? _value; /// - /// Gets or sets the value component value (HSV-color space) of this as degree in the range [0..1]. + /// Gets the value component value (HSV-color space) of this as degree in the range [0..1]. /// - public double Value - { - get => _value ?? (_value = CaclulateValueFromRGB()).Value; - set - { - if (SetProperty(ref _value, value)) - UpdateRGBFromHSV(); - } - } + public double Value { get; } #endregion @@ -187,27 +94,30 @@ namespace RGB.NET.Core /// /// - /// Initializes a new instance of the class. - /// The class created by this constructor equals . - /// - public Color() - : this(0, 0, 0, 0) - { } - - /// - /// - /// Initializes a new instance of the class using only RGB-Values. + /// 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(255, r, g, 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 class using ARGB-values. + /// Initializes a new instance of the struct using ARGB values. /// /// The alpha component value of this . /// The red component value of this . @@ -219,218 +129,172 @@ namespace RGB.NET.Core 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 class using only RGB-Values. - /// Alpha defaults to 255. + /// Initializes a new instance of the struct using ARGB values. /// - /// The hue component value of this . - /// The saturation component value of this . - /// The value component value of this . - public Color(double hue, double saturation, double value) - : this(255, hue, saturation, value) + /// 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 class using ARGB-values. + /// 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 hue component value of this . - /// The saturation component value of this . - /// The value component value of this . - public Color(byte a, double hue, double saturation, double value) - { - this.A = a; - this._hue = hue; - this._saturation = saturation; - this._value = value; - - // ReSharper disable ExplicitCallerInfoArgument - // ReSharper disable VirtualMemberCallInConstructor - OnPropertyChanged(nameof(Hue)); - OnPropertyChanged(nameof(Saturation)); - OnPropertyChanged(nameof(Value)); - // ReSharper restore VirtualMemberCallInConstructor - // ReSharper restore ExplicitCallerInfoArgument - - UpdateRGBFromHSV(); - } + /// 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 class by cloning a existing . + /// 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) - { } + : this(color.A, color.R, color.G, color.B) { } #endregion #region Methods + #region Factory + /// - /// Blends a over this color. + /// Creates a new instance of the struct using HSV-Values. /// - /// The to blend. - public void Blend(Color color) + /// 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) { - if (color.A == 0) return; - - // ReSharper disable once ConvertIfStatementToSwitchStatement - if (color.A == 255) - { - A = color.A; - R = color.R; - G = color.G; - B = color.B; - } - else - { - 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)); - - APercent = resultA; - RPercent = resultR; - GPercent = resultG; - BPercent = resultB; - } + (byte r, byte g, byte b) = CalculateRGBFromHSV(hue, saturation, value); + return new Color(r, g, b); } - private void InvalidateHSV() + /// + /// 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) { - _hue = null; - _saturation = null; - _value = null; - - // ReSharper disable ExplicitCallerInfoArgument - OnPropertyChanged(nameof(Hue)); - OnPropertyChanged(nameof(Saturation)); - OnPropertyChanged(nameof(Value)); - // ReSharper restore ExplicitCallerInfoArgument + (byte r, byte g, byte b) = CalculateRGBFromHSV(hue, saturation, value); + return new Color(a, r, g, b); } - private double CaclulateHueFromRGB() - { - if ((R == G) && (G == B)) return 0.0; + #endregion - double min = Math.Min(Math.Min(R, G), B); - double max = Math.Max(Math.Max(R, G), B); + private static (double h, double s, double v) CaclulateHSVFromRGB(byte r, byte g, byte b) + { + if ((r == g) && (g == b)) return (0, 0, 0); + + int min = Math.Min(Math.Min(r, g), b); + int max = Math.Max(Math.Max(r, g), b); double hue; - if (max.EqualsInTolerance(R)) // r is max - hue = (G - B) / (max - min); - else if (max.EqualsInTolerance(G)) // g is max - hue = 2.0 + ((B - R) / (max - min)); + 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) / (max - min)); + hue = 4.0 + ((r - g) / (double)(max - min)); hue = hue * 60.0; if (hue < 0.0) hue += 360.0; - return hue; + 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 double CaclulateSaturationFromRGB() + private static (byte r, byte g, byte b) CalculateRGBFromHSV(double h, double s, double v) { - int max = Math.Max(R, Math.Max(G, B)); - int min = Math.Min(R, Math.Min(G, B)); + h = h.Wrap(0, 360); + s = s.Clamp(0, 1); + v = v.Clamp(0, 1); - return (max == 0) ? 0 : 1.0 - (min / (double)max); - } - - private double CaclulateValueFromRGB() - { - return Math.Max(R, Math.Max(G, B)) / 255.0; - } - - private void UpdateRGBFromHSV() - { - if (Saturation <= 0.0) + if (s <= 0.0) { - byte val = GetByteValueFromPercentage(Value); - UpdateRGBWithoutInvalidatingHSV(val, val, val); + byte val = v.GetByteValueFromPercentage(); + return (val, val, val); } - double hh = (Hue % 360.0) / 60.0; + double hh = h / 60.0; int i = (int)hh; double ff = hh - i; - double p = Value * (1.0 - Saturation); - double q = Value * (1.0 - (Saturation * ff)); - double t = Value * (1.0 - (Saturation * (1.0 - ff))); + 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: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(Value), - GetByteValueFromPercentage(t), - GetByteValueFromPercentage(p)); - break; + return (v.GetByteValueFromPercentage(), + t.GetByteValueFromPercentage(), + p.GetByteValueFromPercentage()); case 1: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(q), - GetByteValueFromPercentage(Value), - GetByteValueFromPercentage(p)); - break; + return (q.GetByteValueFromPercentage(), + v.GetByteValueFromPercentage(), + p.GetByteValueFromPercentage()); case 2: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(p), - GetByteValueFromPercentage(Value), - GetByteValueFromPercentage(t)); - break; + return (p.GetByteValueFromPercentage(), + v.GetByteValueFromPercentage(), + t.GetByteValueFromPercentage()); case 3: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(p), - GetByteValueFromPercentage(q), - GetByteValueFromPercentage(Value)); - break; + return (p.GetByteValueFromPercentage(), + q.GetByteValueFromPercentage(), + v.GetByteValueFromPercentage()); case 4: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(t), - GetByteValueFromPercentage(p), - GetByteValueFromPercentage(Value)); - break; + return (t.GetByteValueFromPercentage(), + p.GetByteValueFromPercentage(), + v.GetByteValueFromPercentage()); default: - UpdateRGBWithoutInvalidatingHSV(GetByteValueFromPercentage(Value), - GetByteValueFromPercentage(p), - GetByteValueFromPercentage(q)); - break; + return (v.GetByteValueFromPercentage(), + p.GetByteValueFromPercentage(), + q.GetByteValueFromPercentage()); } } - private void UpdateRGBWithoutInvalidatingHSV(byte r, byte g, byte b) - { - _r = r; - _g = g; - _b = b; - - // ReSharper disable ExplicitCallerInfoArgument - OnPropertyChanged(nameof(R)); - OnPropertyChanged(nameof(RPercent)); - OnPropertyChanged(nameof(G)); - OnPropertyChanged(nameof(GPercent)); - OnPropertyChanged(nameof(B)); - OnPropertyChanged(nameof(BPercent)); - // ReSharper enable ExplicitCallerInfoArgument - } - - private static byte GetByteValueFromPercentage(double percentage) - { - if (double.IsNaN(percentage)) return 0; - - percentage = percentage.Clamp(0, 1.0); - return (byte)(percentage.Equals(1.0) ? 255 : percentage * 256.0); - } - /// - /// Converts the individual byte-values of this to a human-readable string. + /// 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() - { - return $"[A: {A}, R: {R}, G: {G}, B: {B}, H: {Hue}, S: {Saturation}, V: {Value}]"; - } + /// 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 . @@ -439,16 +303,9 @@ namespace RGB.NET.Core /// true if is a equivalent to this ; otherwise, false. public override bool Equals(object obj) { - Color compareColor = obj as Color; - if (ReferenceEquals(compareColor, null)) - return false; - - if (ReferenceEquals(this, compareColor)) - return true; - - if (GetType() != compareColor.GetType()) - return false; + if (!(obj is Color)) return false; + Color compareColor = (Color)obj; return (compareColor.A == A) && (compareColor.R == R) && (compareColor.G == G) && (compareColor.B == B); } @@ -468,20 +325,741 @@ namespace RGB.NET.Core } } + #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) + => Color.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) - { - return ReferenceEquals(color1, null) ? ReferenceEquals(color2, null) : color1.Equals(color2); - } + public static bool operator ==(Color color1, Color color2) => color1.Equals(color2); /// /// Returns a value that indicates whether two specified are equal. @@ -489,10 +1067,21 @@ namespace RGB.NET.Core /// The first to compare. /// The second to compare. /// true if and are not equal; otherwise, false. - public static bool operator !=(Color color1, Color color2) - { - return !(color1 == color2); - } + 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/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 5854bf6..a97c4bd 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -60,7 +60,7 @@ namespace RGB.NET.Core /// public Color RequestedColor { - get => new Color(_requestedColor); + get => _requestedColor; private set { SetProperty(ref _requestedColor, value); @@ -80,15 +80,7 @@ namespace RGB.NET.Core set { if (!IsLocked) - { - // DarthAffe 26.01.2017: DON'T USE THE PROPERTY HERE! Working on the copy doesn't work! - _requestedColor.Blend(value); - - // ReSharper disable ExplicitCallerInfoArgument - OnPropertyChanged(nameof(RequestedColor)); - OnPropertyChanged(nameof(IsDirty)); - // ReSharper restore ExplicitCallerInfoArgument - } + RequestedColor += value; } } @@ -168,19 +160,13 @@ namespace RGB.NET.Core /// Converts a to a . /// /// The to convert. - public static implicit operator Color(Led led) - { - return led?.Color; - } + public static implicit operator Color(Led led) => led?.Color ?? Color.Transparent; /// /// Converts a to a . /// /// The to convert. - public static implicit operator Rectangle(Led led) - { - return led?.LedRectangle; - } + public static implicit operator Rectangle(Led led) => led?.LedRectangle; #endregion } diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs index 0ca16a7..8d05d55 100644 --- a/RGB.NET.Core/Positioning/Point.cs +++ b/RGB.NET.Core/Positioning/Point.cs @@ -140,11 +140,11 @@ namespace RGB.NET.Core } /// - /// Returns a new representing the substraction of the two provided . + /// Returns a new representing the subtraction of the two provided . /// /// The first . /// The second . - /// A new representing the substraction of the two provided . + /// A new representing the subtraction of the two provided . public static Point operator -(Point point1, Point point2) { return new Point(point1.X - point2.X, point1.Y - point2.Y); diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs index 0e36567..8cc8cd0 100644 --- a/RGB.NET.Core/Positioning/Size.cs +++ b/RGB.NET.Core/Positioning/Size.cs @@ -149,11 +149,11 @@ namespace RGB.NET.Core } /// - /// Returns a new representing the substraction of the two provided . + /// Returns a new representing the subtraction of the two provided . /// /// The first . /// The second . - /// A new representing the substraction of the two provided . + /// A new representing the subtraction of the two provided . public static Size operator -(Size size1, Size size2) { return new Size(size1.Width - size2.Width, size1.Height - size2.Height); diff --git a/RGB.NET.Core/RGB.NET.Core.csproj b/RGB.NET.Core/RGB.NET.Core.csproj index ae6c793..429140a 100644 --- a/RGB.NET.Core/RGB.NET.Core.csproj +++ b/RGB.NET.Core/RGB.NET.Core.csproj @@ -80,7 +80,7 @@ - + diff --git a/RGB.NET.Decorators/Brush/FlashDecorator.cs b/RGB.NET.Decorators/Brush/FlashDecorator.cs index c4d79ba..1d7daff 100644 --- a/RGB.NET.Decorators/Brush/FlashDecorator.cs +++ b/RGB.NET.Decorators/Brush/FlashDecorator.cs @@ -72,7 +72,7 @@ namespace RGB.NET.Decorators.Brush #region Methods /// - public void ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, ref Color color) => color.APercent = _currentValue; + public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) => color.SetAPercent(_currentValue); /// protected override void Update(double deltaTime) diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs index 1a6bc33..c7a904b 100644 --- a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs +++ b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs @@ -151,7 +151,7 @@ namespace RGB.NET.Devices.Corsair for (int i = 0; i < LedMapping.Count; i++) { _CorsairLedColor ledColor = (_CorsairLedColor)Marshal.PtrToStructure(readPtr, typeof(_CorsairLedColor)); - colorData.Add((CorsairLedIds)ledColor.ledId, new Color((byte)ledColor.r, (byte)ledColor.g, (byte)ledColor.b)); + colorData.Add((CorsairLedIds)ledColor.ledId, new Color(ledColor.r, ledColor.g, ledColor.b)); readPtr = new IntPtr(readPtr.ToInt64() + structSize); } diff --git a/RGB.NET.WPF/Converter/ColorToSolidColorBrushConverter.cs b/RGB.NET.WPF/Converter/ColorToSolidColorBrushConverter.cs index c76b64b..4dea27d 100644 --- a/RGB.NET.WPF/Converter/ColorToSolidColorBrushConverter.cs +++ b/RGB.NET.WPF/Converter/ColorToSolidColorBrushConverter.cs @@ -15,8 +15,7 @@ namespace RGB.NET.WPF.Converter /// public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - Core.Color color = value as Core.Color; - return new SolidColorBrush(color == null + return new SolidColorBrush(!(value is Core.Color color) ? Color.FromArgb(0, 0, 0, 0) : Color.FromArgb(color.A, color.R, color.G, color.B)); }