// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. using System; using System.Globalization; using System.Runtime.InteropServices; using System.Runtime.Serialization; namespace math { /// /// Represents a color in the form of Hue, Saturation, Value, Alpha. /// [DataContract( Name = "ColorHSV")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct ColorHSV : IEquatable, IFormattable { private const string ToStringFormat = "Hue:{0} Saturation:{1} Value:{2} Alpha:{3}"; /// /// The Hue of the color. /// [DataMember( Order = 0 )] public float H; /// /// The Saturation of the color. /// [DataMember( Order = 1 )] public float S; /// /// The Value of the color. /// [DataMember( Order = 2 )] public float V; /// /// The alpha component of the color. /// [DataMember( Order = 3 )] public float A; /// /// Initializes a new instance of the struct. /// /// The h. /// The s. /// The v. /// A. public ColorHSV(float h, float s, float v, float a) { H = h; S = s; V = v; A = a; } /// /// Converts the color into a three component vector. /// /// A three component vector containing the red, green, and blue components of the color. public Color4 ToColor() { float hdiv = H / 60; int hi = (int)hdiv; float f = hdiv - hi; float p = V * (1 - S); float q = V * (1 - (S * f)); float t = V * (1 - (S * (1 - f))); switch (hi) { case 0: return new Color4(V, t, p, A); case 1: return new Color4(q, V, p, A); case 2: return new Color4(p, V, t, A); case 3: return new Color4(p, q, V, A); case 4: return new Color4(t, p, V, A); default: return new Color4(V, p, q, A); } } /// /// Converts the color into a HSV color. /// /// The color. /// A HSV color public static ColorHSV FromColor(Color4 color) { float max = Math.Max(color.R, Math.Max(color.G, color.B)); float min = Math.Min(color.R, Math.Min(color.G, color.B)); float delta = max - min; float h = 0.0f; if (delta > 0.0f) { if (color.R >= max) h = (color.G - color.B) / delta; else if (color.G >= max) h = (color.B - color.R) / delta + 2.0f; else h = (color.R - color.G) / delta + 4.0f; h *= 60.0f; if (h < 0) h += 360f; } float s = MathUtil.IsZero(max) ? 0.0f : delta / max; return new ColorHSV(h, s, max, color.A); } /// public bool Equals(ColorHSV other) { return other.H.Equals(H) && other.S.Equals(S) && other.V.Equals(V) && other.A.Equals(A); } /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof(ColorHSV)) return false; return Equals((ColorHSV)obj); } /// public override int GetHashCode() { unchecked { int result = H.GetHashCode(); result = (result * 397) ^ S.GetHashCode(); result = (result * 397) ^ V.GetHashCode(); result = (result * 397) ^ A.GetHashCode(); return result; } } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return ToString(CultureInfo.CurrentCulture); } /// /// Returns a that represents this instance. /// /// The format. /// /// A that represents this instance. /// public string ToString(string format) { return ToString(format, CultureInfo.CurrentCulture); } /// /// Returns a that represents this instance. /// /// The format provider. /// /// A that represents this instance. /// public string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, ToStringFormat, H, S, V, A); } /// /// Returns a that represents this instance. /// /// The format. /// The format provider. /// /// A that represents this instance. /// public string ToString(string format, IFormatProvider formatProvider) { if (format == null) return ToString(formatProvider); return string.Format(formatProvider, ToStringFormat, H.ToString(format, formatProvider), S.ToString(format, formatProvider), V.ToString(format, formatProvider), A.ToString(format, formatProvider)); } } }