# Transformation between the hue color wheel and Itten's color wheel

Unfortunately, the hue color wheel does not correspond to human visual perception: Equal differences of the hue angle are perceived as different color differences. E.g. yellow takes only a small range of angles in the color wheel, see https://de.wikipedia.org/wiki/Farbkreis, second figure, for an example.

There are correctives for this issue such as Itten's color wheel.

My question: Are there equations that translate the angle of the hue color wheel into that of Itten's color wheel and vice versa? Of course, an interpolation of values at distinct angles could also work but equations might be better. Distinct angles are given here: https://uxplanet.org/algorithm-for-automatic-harmonious-color-selection-for-the-image-fc26dde69ca1#.lnuwum51m, halfway down.

Item's colour wheel is also clearly uneven perpetually and the colours vary between different printings and even on different pages of the same copy. If you want a more perpetually even space use either Munsell or Lab space. Photoshop converts between rgb hue angle and Lab coordinates and you can easily calculate a hue angle from the a and b coordinates of Lab.

• Munsell space is by far the best... But a bit hard to come by. – joojaa Aug 13 '16 at 21:22

Interestingly enough the second link you added has a figure of Itten's color model, but actually uses HSB for its calculations.

However it seems like you want to be able to convert the "Hue" value of HSV from the HSV color wheel to Itten's color wheel like so: You can see that on the first wheel the values of red, blue, and green are at 0, 120, and 240 degrees respectively. On the second it is red, yellow, and blue at the same places. So what you need to do is convert from RGB to RYB. Here is my implementation in C#, largely cribbed from here (all copied here in case the source one day goes down)::

``````private Color RGBToRYB(Color color)
{

// Remove the white from the color
float iWhite = Mathf.Min(color.r, color.g, color.b);
float iRed = color.r - iWhite;
float iGreen = color.g - iWhite;
float iBlue = color.b - iWhite;

float iMaxGreen = Mathf.Max(iRed, iGreen, iBlue);

// Get the yellow out of the red+green
float iYellow = Mathf.Min(iRed, iGreen);
iRed -= iYellow;
iGreen -= iYellow;

// If this unfortunate conversion combines blue and green, then cut each in half to
// preserve the value's maximum range.
if (iBlue > 0f && iGreen > 0f)
{
iBlue /= 2f;
iGreen /= 2f;
}

// Redistribute the remaining green.
iYellow += iGreen;
iBlue += iGreen;

// Normalize to values.
float iMaxYellow = Mathf.Max(iRed, iYellow, iBlue);

if (iMaxYellow > 0f)
{
float iN = iMaxGreen / iMaxYellow;

iRed *= iN;
iYellow *= iN;
iBlue *= iN;
}

// Add the white back in.
iRed += iWhite;
iYellow += iWhite;
iBlue += iWhite;

return (new Color(iRed, iYellow, iBlue));

}
``````

But that only gets you RYB, which while useful for operations based on Itten's color wheel, isn't useful for much by itself at all. So what I did is convert to HSV, which can be easily done using any stock RGB to HSV function, but where you pass "Y" instead of "G".

``````private Vector3 RYBToHSV(Vector3 color)
{
float r = color, y = color, b = color;
float mx = Mathf.Max(r, y, b);
float mn = Mathf.Min(r, y, b);
float df = mx - mn;
float h, s, v;
if (mx == mn)
{
h = 0.0f;
}
else if (mx == r)
{
h = (60.0f * ((y - b) / df) + 360.0f) % 360.0f;
}
else if (mx == y)
{
h = (60.0f * ((b - r) / df) + 120.0f) % 360.0f;
}
else if (mx == b)
{
h = (60.0f * ((r - y) / df) + 240.0f) % 360.0f;
}
else
{
h = 0;
}

if (mx == 0f)
{
s = 0.0f;
}
else
{
s = (df / mx) * 100.0f;
}
v = mx * 100.0f;
return new Vector3(h / 360.0f, s / 100.0f, v / 100.0f);
}
``````