/// <summary> /// This method creates a VBO for the JND Ellipses for the selected Color with the values for McAdams Ellipses (0.055f) /// /// The method first points to several directions with aequidistance angle and creates a line with points /// the points will taken to compute jnd until threshold is reached and breaks to take the next line /// </summary> /// <param name="color">the selected Color</param> /// <returns>returns a VBO with the Ellipse value</returns> /// <author>Markus Strobel, Justine Smyzek</author> private VBO createJNDEllipse(Yxy color) { int lines = 36; double degreeStep = 360d / lines; List<Vector2>[] linesArray = new List<Vector2>[lines]; // generate lines to check for (int i = 0; i < lines; i++) { List<Vector2> linePoints = new List<Vector2>(); double xOffSet = 0d; double yOffSet = 0d; // generate all vertices for each line for (double radius = 0.0001d; radius < 0.1d; radius += 0.0001d) { xOffSet = radius * Math.Cos((i * degreeStep) * Math.PI / 180d); yOffSet = radius * Math.Sin((i * degreeStep) * Math.PI / 180d); linePoints.Add(new Vector2((float) (color.x + xOffSet), (float) (color.y + yOffSet))); } linesArray[i] = linePoints; } float jnd = 0.0055f; // value of McAdams Ellipsen List<Vector3> vertices = new List<Vector3>(); List<int> indices = new List<int>(); int ind = 0; // compute JND foreach(List<Vector2> line in linesArray) { foreach(Vector2 point in line) { float result = 0f; Yxy comp = new Yxy(point.X, point.Y); result = ColorHelper.Chromatic_Difference(color.asXYZ(), comp.asXYZ()); if (result > jnd) { vertices.Add(new Vector3(point.X, point.Y, 0f)); indices.Add(ind++); break; } } } return LoadVBO(vertices.ToArray(), indices.ToArray()); }
/// <summary> /// mouse hover ofer the OpenGL Window will be handled here /// </summary> /// <author>Markus Strobel</author> private void glControl_MouseHover(object sender, System.EventArgs e) { // Get current mouse position within the glControl Point mousePos = glControl1.PointToClient(Cursor.Position); // get x,y relative to an origin in the bottom left float x = mousePos.X; float y = glControl1.Height - mousePos.Y; // normalize to 0..1 x /= glControl1.Width; y /= glControl1.Height; if (radioButtonXYZView.Checked) { Yxy Yxy = new Yxy(x, y); hoveredXYZColor = Yxy.asXYZ(); hoveredRGBColor = hoveredXYZColor.asRGB(); //FarbRechner.CIEXYZ_to_RGB(FarbRechner.CIEYxy_to_CIEXYZ(Yxy)); x = (float)Math.Round((double)x, 2); y = (float)Math.Round((double)y, 2); // filter negative rgb values if (!(hoveredRGBColor.R < 0 || hoveredRGBColor.G < 0 || hoveredRGBColor.B < 0)) { try { // normalize float maxV = Math.Max(hoveredRGBColor.R, Math.Max(hoveredRGBColor.G, hoveredRGBColor.B)); hoveredRGBColor.R /= maxV; hoveredRGBColor.G /= maxV; hoveredRGBColor.B /= maxV; // gamma correction hoveredRGBColor.R = ColorHelper.Reverse_Gamma_Correction(hoveredRGBColor.R); hoveredRGBColor.G = ColorHelper.Reverse_Gamma_Correction(hoveredRGBColor.G); hoveredRGBColor.B = ColorHelper.Reverse_Gamma_Correction(hoveredRGBColor.B); panelColorPreview.BackColor = Color.FromArgb((int)(hoveredRGBColor.R * 255), (int)(hoveredRGBColor.G * 255), (int)(hoveredRGBColor.B * 255)); labelColorPreviewHex.Text = "#" + ((int)(hoveredRGBColor.R * 255)).ToString("X") + ((int)(hoveredRGBColor.G * 255)).ToString("X") + ((int)(hoveredRGBColor.B * 255)).ToString("X"); } catch { labelColorPreviewHex.Text = "#000"; panelColorPreview.BackColor = Color.Black; } } else { labelColorPreviewHex.Text = "#000"; panelColorPreview.BackColor = Color.Black; } labelColPreviewXH.Text = "x: " + x.ToString(); labelColPreviewYS.Text = "y: " + y.ToString(); } }
/// <summary> /// this method performs all tasks done with a left mouse click in XYZ space /// </summary> /// <param name="x">the current x coordinate</param> /// <param name="y">the current y coordinate</param> /// <param name="showCircle">if true the selected Color circle will be shown</param> /// <author>Markus Strobel</author> private void LeftClickXYZSpace(float x, float y, bool showCircle) { // set trackbar values if (!(hoveredRGBColor.R < 0 || hoveredRGBColor.G < 0 || hoveredRGBColor.B < 0)) { HSL hsl = hoveredRGBColor.asHSL(); // normalize float maxV = Math.Max(hoveredRGBColor.R, Math.Max(hoveredRGBColor.G, hoveredRGBColor.B)); hoveredRGBColor.R /= maxV; hoveredRGBColor.G /= maxV; hoveredRGBColor.B /= maxV; // set RGB tab values for trackbars labelTabRGB_R.Text = "R: " + hoveredRGBColor.R; labelTabRGB_G.Text = "G: " + hoveredRGBColor.G; labelTabRGB_B.Text = "B: " + hoveredRGBColor.B; trackBarR.Value = (int)(hoveredRGBColor.R * 255); trackBarG.Value = (int)(hoveredRGBColor.G * 255); trackBarB.Value = (int)(hoveredRGBColor.B * 255); //set HSL values for trackbars labelTabHSL_H.Text = "H: " + (hsl.H) + "°"; labelTabHSL_S.Text = "S: " + (hsl.S * 100) + "%"; labelTabHSL_L.Text = "L: " + (hsl.L * 100) + "%"; trackBarH.Value = (int)hsl.H; trackBarS.Value = (int)(hsl.S * 100); trackBarL.Value = (int)(hsl.L * 100); selectedRGBColor = hoveredRGBColor; selectedXYZColor = hoveredXYZColor; selectedYxyColor = new Yxy(x, y); if (checkBoxRGB.Checked) { showColorCircle = false; createRGBPreviewLines(selectedRGBColor); } else if (checkBoxHSL.Checked) { showColorCircle = false; createHSLPreviewLines(selectedRGBColor.asHSL()); createHSLPreviewCircle(selectedRGBColor.asHSL()); } else { showColorCircle = showCircle; createSelectedColorCircleVBO(x, y, 0.01f, 36); // computes color circle position } } else // (!(hoveredRGBColor.R < 0 || hoveredRGBColor.G < 0 || hoveredRGBColor.B < 0)) { trackBarR.Value = 0; trackBarG.Value = 0; trackBarB.Value = 0; labelTabRGB_R.Text = "R: 0"; labelTabRGB_G.Text = "G: 0"; labelTabRGB_B.Text = "B: 0"; trackBarH.Value = 1; trackBarS.Value = 100; trackBarL.Value = 50; labelTabHSL_H.Text = "H: 1°"; labelTabHSL_S.Text = "S: 100%"; labelTabHSL_L.Text = "L: 50%"; selectedRGBColor = null; selectedXYZColor = null; showColorCircle = false; } // take current preview Color as selected Color // we dont need to compute it twice // set selectedColor Panel, label panelColorSelected.BackColor = panelColorPreview.BackColor; labelColorSelectedHex.Text = labelColorPreviewHex.Text; labelColSelectedXH.Text = labelColPreviewXH.Text; labelColSelectedYS.Text = labelColPreviewYS.Text; }
/// <summary> /// transformatin CIE XYZ -> Yxy /// </summary> /// <author>Birthe Anne Wiegand</author> /// <returns>Yxy value</returns> public Yxy asYxy() { Yxy temp = new Yxy(); // transformation CIE XYZ -> Yxy (luminance Y = 1 temp.Y = 1f; temp.x = this.X / (this.X + this.Y + this.Z); temp.y = this.Y / (this.X + this.Y + this.Z); return temp; }