private void Single_HslHsvHsl(HSLColor color) { float h, s, v; color.ToHSV(out h, out s, out v); var color2 = HSLColor.FromHSV(h, s, v); color2.a = color.a; float linv = 1 - color.l; if (color.l == 1 && color.s != 0) { // Conversion to HSV necessarily requires that HSV.s==1. // Saturation won't be able to round-trip exactly. AssertNearlyEqualHSL(color, color2); } else if (linv < 3e-4f) { // And when l is nearly 1, the saturation calculation starts // getting numerically unstable. AssertNearlyEqualHSL(color, color2); } else { AssertNearlyEqualHSLStrict(color, color2); } }
/// Returns true on success, false on failure. /// Failure cases are guaranteed to be identical to the failure cases of RawValueToColor /// Use if converting raw -> Color is lossy; otherwise, use RawValueToColor /// HDR color pickers might disallow conversion to HSL. static bool RawValueToHSLColor(ColorPickerMode mode, Vector3 raw, out HSLColor color) { const float EPSILON = 1e-5f; switch (mode) { case ColorPickerMode.SV_H_Rect: color = HSLColor.FromHSV(raw.z * HSLColor.HUE_MAX, raw.x, raw.y); return(true); case ColorPickerMode.HS_L_Polar: { var position = new Vector2(raw.x - 0.5f, raw.y - 0.5f) * 2; var radius = position.magnitude; color = new HSLColor(); if (radius > 1) { if (radius > 1 + EPSILON) { return(false); } else { radius = 1; } } // x direction is 0 degrees (red) color.HueDegrees = Mathf.Atan2(position.y, position.x) * Mathf.Rad2Deg; color.s = radius; color.l = raw.z; color.a = 1; return(true); } case ColorPickerMode.SL_H_Triangle: { color.h = 0; // assigned later color.l = raw.y; float maxChroma = SQRT3 * ((color.l < .5f) ? color.l : (1 - color.l)); color.s = (maxChroma == 0) ? 0 : raw.x / maxChroma; color.a = 1; color.Hue01 = raw.z; return(0 <= raw.x && raw.x <= maxChroma); } case ColorPickerMode.HL_S_Polar: { var position = new Vector2(raw.x - 0.5f, raw.y - 0.5f) * 2; var radius = position.magnitude; color = new HSLColor(); if (radius > 1) { if (radius > 1 + EPSILON) { return(false); } else { radius = 1; } } color.HueDegrees = Mathf.Atan2(position.y, position.x) * Mathf.Rad2Deg; color.l = 1 - radius; color.s = 1 - raw.z; color.a = 1; return(true); } case ColorPickerMode.HS_LogV_Polar: throw new InvalidOperationException("This is a HDR mode"); default: Debug.Assert(false); color = new HSLColor(); return(false); } }