private void OnGUI() { PrepareStyles(); UpdatePickerCoordinates(); EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck(); colourModel = (Colour.Model)EditorGUILayout.Popup("Colour Space", (int)colourModel, System.Enum.GetNames(typeof(Colour.Model))); sliderAxis = (SliderAxis)EditorGUILayout.Popup("Slider Axis", (int)sliderAxis, System.Enum.GetNames(typeof(SliderAxis))); workingSpace = (Colour.RGBSpace)EditorGUILayout.Popup("Working Colour Space", (int)workingSpace, System.Enum.GetNames(typeof(Colour.RGBSpace))); if (EditorGUI.EndChangeCheck()) { Double3 newPickFrac = GetPickerCoords(currentColourXYZ, colourModel, workingSpace); Double3 pick = newPickFrac * maxValue; pickerCoords = new Int4(Mathf.RoundToInt((float)pick.x), Mathf.RoundToInt((float)pick.y), Mathf.RoundToInt((float)pick.z), pickerCoords.w); } limitingSpace = (Colour.RGBSpace)EditorGUILayout.Popup("Limiting Colour Space", (int)limitingSpace, System.Enum.GetNames(typeof(Colour.RGBSpace))); if (EditorGUI.EndChangeCheck()) { pickerOutOfDate = sliderOutOfDate = true; } EditorGUILayout.Space(); EditorGUILayout.ColorField(currentColourRGB); minSize = maxSize = new Vector2(textureSize + 60, textureSize + 280); UpdateTextures(); GUI.DrawTexture(pickerRect, pickerTexture, ScaleMode.StretchToFill); GUI.DrawTexture(sliderRect, sliderTexture, ScaleMode.StretchToFill); for (int i = 0; i < altSliders; ++i) GUI.DrawTexture(sliderGroupRect[i], sliderGroupTexture[i], ScaleMode.StretchToFill); int circleSize = 8; int halfCircleSize = 4; if (Event.current.type == EventType.Repaint) { pickerBox.Draw(pickerRect, GUIContent.none, 0); pickerBox.Draw(sliderRect, GUIContent.none, 0); pickerCircle.Draw(new Rect(pickerCoords.x + 10 - halfCircleSize, ((textureSize - 1) - (pickerCoords.y)) + 120 - halfCircleSize, circleSize, circleSize), GUIContent.none, 0); sliderVertArrow.Draw(new Rect(textureSize + 18, (textureSize - 1) - (pickerCoords.z) + 117, 34, 8), GUIContent.none, 0); for (int i = 0; i < altSliders; ++i) { sliderHorizArrow.Draw(new Rect(pickerCoords[i] + 7, sliderGroupRect[i].yMin - 4, 16, 28), GUIContent.none, 0); pickerBox.Draw(sliderGroupRect[i], GUIContent.none, 0); } } Double4 pickerPosFraction = pickerCoords / maxValue; if (pickerOutOfDate == true || sliderOutOfDate == true) { Double4 arrangement = GetPickerArrangement(sliderAxis, pickerPosFraction); Colour pickedColour = GetWorkingSpaceColour(colourModel, workingSpace, arrangement); if (Colour.IsInsideGamut(pickedColour, limitingSpace)) { currentColourXYZ = pickedColour; currentColourRGB = (Color)Colour.To_RGB(pickedColour, workingSpace); } else { currentColourXYZ = new Colour(Double3.zero); currentColourRGB = Color.black; } } currentColourRGB.a = (float)pickerPosFraction.w; Repaint(); pickerOutOfDate = sliderOutOfDate = false; }
private static Double3 GetPickerCoords(Colour col, Colour.Model newModel, Colour.RGBSpace workingSpace) { Double3 coords = Double3.zero; if (newModel == Colour.Model.RGB) coords = Colour.To_RGB(col, workingSpace); else if (newModel == Colour.Model.xyY) coords = Colour.To_xyY(col); else if (newModel == Colour.Model.HSL) coords = Colour.To_HSL(col, workingSpace); else if (newModel == Colour.Model.HSV) coords = Colour.To_HSV(col, workingSpace); else if (newModel == Colour.Model.XYZ) coords = new Double3(col.X, col.Y, col.Z); else if (newModel == Colour.Model.Lab) coords = Colour.To_Lab(col); //else if (originalModel == Colour.Model.LCH) //workingSpaceColour = Colour.From_LCH((Double3)arrangement); return coords; }
private static Colour GetWorkingSpaceColour(Colour.Model originalModel, Colour.RGBSpace workingSpace, Double4 arrangement) { Colour workingSpaceColour = new Colour(Double3.zero); if (originalModel == Colour.Model.RGB) workingSpaceColour = Colour.From_RGB((Double3)arrangement, workingSpace); else if (originalModel == Colour.Model.xyY) workingSpaceColour = Colour.From_xyY((Double3)arrangement); else if (originalModel == Colour.Model.HSL) workingSpaceColour = Colour.From_HSL((Double3)arrangement, workingSpace); else if (originalModel == Colour.Model.HSV) workingSpaceColour = Colour.From_HSV((Double3)arrangement, workingSpace); else if (originalModel == Colour.Model.XYZ) workingSpaceColour = new Colour((Double3)arrangement); else if (originalModel == Colour.Model.Lab) workingSpaceColour = Colour.From_Lab((Double3)arrangement); //else if (originalModel == Colour.Model.LCH) //workingSpaceColour = Colour.From_LCH((Double3)arrangement); return workingSpaceColour; }
public static Double3 To_RGB(Colour col, RGBSpace space) { RGBDefinition d = rgbSpaces[space]; Double3 linear = d.fromXYZ * col.val; return Mathd.Pow(linear, 1.0 / d.gamma); }
public static Double3 To_xyY(Colour col) { return new Double3(col.X / (col.X + col.Y + col.Z), col.Y / (col.X + col.Y + col.Z), col.Y); }
public static Double3 To_Lab(Colour col) { Double3 lab = new Double3(); Double3 w = new Double3(95.047, 100.000, 108.883); System.Func<double, double> f = new System.Func<double, double>((x) => { if (x > Mathd.Pow(6.0 / 29.0, 3)) return Mathd.Pow(x, (1.0 / 3.0)); else return ((1.0 / 3.0) * Mathd.Pow(29.0 / 6.0, 2.0) * x) + (4.0 / 29.0); }); lab.x = (166.0 * f(col.Y / w.y)) - 16; lab.y = 500.0 * (f(col.X / w.x) - f(col.Y / w.y)); lab.z = 200.0 * (f(col.Y / w.y) - f(col.Z / w.z)); lab.x = (lab.x + 15) * (1.0 / 30.0); lab.y = (lab.y + 30) * (1.0 / 50.0); lab.z = (lab.z + 30) * (1.0 / 50.0); return lab; }
public static Double3 To_HSV(Colour col, RGBSpace space) { Double3 hsv; Double3 rgb = To_RGB(col, space); double min = Mathd.Min(rgb.x, rgb.y, rgb.z); double max = Mathd.Max(rgb.x, rgb.y, rgb.z); double delta = max - min; if (max == 0) { return new Double3(0, 0, 0); } hsv.y = delta / max; hsv.z = max; if (rgb.x == max) hsv.x = (rgb.y - rgb.z) / delta; else if (rgb.y == max) hsv.x = 2 + (rgb.z - rgb.x) / delta; else hsv.x = 4 + (rgb.x - rgb.y) / delta; hsv.x *= 60; if (hsv.x < 0) hsv.x += 360; return hsv; }
public static Double3 To_HSL(Colour col, RGBSpace space) { Double3 hsl; Double3 rgb = To_RGB(col, space); double min = Mathd.Min(rgb.x, rgb.y, rgb.z); double max = Mathd.Max(rgb.x, rgb.y, rgb.z); double delta = max - min; hsl.z = max - min / 2.0; if (delta == 0) { hsl.x = 0; hsl.y = 0; return hsl; } if (rgb.x == max) hsl.x = (rgb.y - rgb.z) / delta; else if (rgb.y == max) hsl.x = 2 + (rgb.z - rgb.x) / delta; else hsl.x = 4 + (rgb.x - rgb.y) / delta; hsl.x *= 60; if (hsl.x < 0) hsl.x += 360; hsl.y = delta / (1 - (Mathd.Abs((2.0 * hsl.z) - 1))); return hsl; }
public static bool IsInsideGamut(Colour currentColour, RGBSpace limitingSpace) { Double3 limitingGamutColour = To_RGB(currentColour, limitingSpace); if (limitingGamutColour.MaxVal > 1.0 || limitingGamutColour.MinVal < 0.0 || double.IsNaN(limitingGamutColour.x) || double.IsNaN(limitingGamutColour.y) || double.IsNaN(limitingGamutColour.z)) return false; return true; }
public static Colour From_Lab(Double3 lab) { lab.x = (lab.x * 30) - 15; lab.y = (lab.y * 60) - 30; lab.z = (lab.z * 60) - 30; Colour col = new Colour(); Double3 w = new Double3(95.047, 100.000, 108.883); System.Func<double, double> f = new System.Func<double, double>((x) => { if (x > Mathd.Pow(6.0 / 29.0, 3.0)) return Mathd.Pow(x, 3.0); else return 3.0 * Mathd.Pow(6.0 / 29.0, 2.0) * (x - (4.0 / 29.0)); }); col.X = w.x * f(((1.0 / 116.0) * (lab.x + 16)) + ((1.0 / 500.0) * lab.y)); col.Y = w.y * f((1.0 / 116.0) * (lab.x + 16)); col.Z = w.z * f(((1.0 / 116.0) * (lab.x + 16)) - ((1.0 / 200.0) * lab.z)); return col; }