# RYB and RGB color space conversion

I am working on a project where I need to convert colors defined in RGB (Red, Green, Blue) color space to RYB (Red Yellow Blue).

I managed to solve converting a color from RYB to RGB space based on this article: http://vis.computer.org/vis2004/DVD/infovis/papers/gossett.pdf

I convert a color from RYB to RGB with this "algorithm":

So the values of r (red), y (yellow), and b (blue) are known, also these arrays/sets are constants:

white: [1, 1, 1]
red: [1, 0, 0]
yellow: [1, 1, 0]
blue: [0.163, 0.373, 0.6]
violet: [0.5, 0, 0.5]
green: [0, 0.66, 0.2]
orange: [1, 0.5, 0]
black: [0.2, 0.094, 0.0]


here is how I calculate the value of red for the RGB space based on the parameters above:

i = 1;
rgb_red = white[i] * (1 - r) * (1 - b) * (1 - y) +
red[i] * r * (1 - b) * (1 - y) +
blue[i] * (1 - r) * b * (1 - y) +
violet[i] * r * b * (1 - y) +
yellow[i] * (1 - r) * (1 - b) * y +
orange[i] * r * (1 - b) * y +
green[i] * (1 - r) * b * y +
black[i] * r * b * y);


for rgb_green exactly the same thing but for i=2, and i=3 for rgb_blue.

My problem is that now I want to convert from RGB to RYB back. In other words, knowing the values of rgb_red, rgb_green and rgb_blue I want to calculate the values of r, y, and b. So I need a kind of inverse function for this, but I don't know how to get it.

Any help is appreciated.

-

Having read the linked paper, I now understand a lot more of what you are doing here than what you have explained. And I think I can help solve your problem.

The authors perform the conversion from RYB to RGB via a trilinear interpolation. In essence, they provide explicit values of a mapping from RYB to RGB on the corners of an RYB cube—i.e. every point $(r,y,b)$ where $r$, $y$, and $b$ are all $1$ or $0$—and they linearly interpolate along the three axes everywhere else.

Let us call that mapping $f: \textrm{RYB} \rightarrow \textrm{RGB}$, where $f$ takes an $(r,y,b)$ triplet to an $(R,G,B)$ triplet. (I will use lowercase for RYB and uppercase for RGB throughout.) The interpolation is defined by the following facts: \begin{align} \textrm{RYB}&\rightarrow\textrm{RGB}\\ f(0,0,0)&=(1,1,1)\\ f(0,0,1)&=(0.163, 0.373, 0.6)\\ f(0,1,0)&=(1,1,0)\\ f(0,1,1)&=(0, 0.66, 0.2)\\ f(1,0,0)&=(1,0,0)\\ f(1,0,1)&=(.5,.5,0)\\ f(1,1,0)&=(1,.5,0)\\ f(1,1,1)&=(0.2, 0.094, 0.0)\\ f(r,y,b)&=f(0,0,0)(1-r)(1-y)(1-b)+f(0,0,1)(1-r)(1-y)b\\ &\;+f(0,1,0)(1-r)y(1-b)+f(1,0,0)r(1-y)(1-b)\\ &\;+f(0,1,1)(1-r)yb+f(1,0,1)r(1-y)b\\ &\;+f(1,1,0)ry(1-b)+f(1,1,1)ryb \end{align} where the subscript $c$ denotes a value at the corners.

You now want to solve the opposite problem. You want a function $f^{-1}: \textrm{RGB} \rightarrow \textrm{RYB}$ which takes a triplet $(R,G,B)$ to a triplet $(r,y,b)$. It seems to me that an easier problem to solve is to go through the same process as the authors of the linked paper did: find the RYB values of all the colors at the corners of an RGB cube and interpolate between them. This will give you a function $F: \textrm{RGB} \rightarrow \textrm{RYB}$ which might not be exactly equal to $f^{-1}$ but will hopefully be close enough for what you need.

\begin{align} \textrm{RGB}&\rightarrow\textrm{RYB}\\ F(0,0,0)&=?\\ F(0,0,1)&=?\\ F(0,1,0)&=?\\ F(0,1,1)&=?\\ F(1,0,0)&=(1,0,0)\\ F(1,0,1)&=?\\ F(1,1,0)&=(0,1,0)\\ F(1,1,1)&=(0,0,0)\\ F(R,G,B)&=F(0,0,0)(1-R)(1-G)(1-B)+F(0,0,1)(1-R)(1-G)B\\ &\;+F(0,1,0)(1-R)G(1-B)+F(1,0,0)R(1-G)(1-B)\\ &\;+F(0,1,1)(1-R)GB+F(1,0,1)R(1-G)B\\ &\;+F(1,1,0)RG(1-B)+F(1,1,1)RGB. \end{align}

The task that remains is to fill in those blanks. I would recommend coding up $f$ in something like Mathematica and finding the values $(r,y,b)$ where $f(r,y,b)=(R_c,G_c,B_c)$ for the values at the corners of the RGB cube. Then set $F(R_c,G_c,B_c)=(r,y,b)$ for the values you just found. Good luck!

-
First, thank you for reading the article to understand my problem more deeply. Appreciate it! As you mentioned, the same method can be used for RGB -> RYB. I actually don't necessarily need the inverse function of RYB -> RGB in the "mathematical meaning", but much more an inverse algorithm. Thank you for poiting this out. I will try to implement it, and I'll back with my results! – Tamás Pap Feb 16 '13 at 16:57
I implemented $f$ in Mathematica as discussed, and used FindRoot to find $(r,y,b)$ values to produce the $(R_c,G_c,B_c)$ corner values. It... was not incredibly successful. The output seems to depend sensitively on the "initial guess" $(r_0,y_0,b_0)$ and often tries to push the values outside the domain $[0,1]$. – Flavin Feb 16 '13 at 18:18

When i wrote a program to convert between all majorly used color formats, i used the following algorithms for $RYB \rightarrow RGB$ and $RGB \rightarrow RYB$ conversion: http: //www.insanit.net/tag/rgb-to-ryb/ [note: link now points to malware]

Now I don't know if this solution works perfectly with the conversion you already have, it looks like some kind of matrix multiplication. If we split $(1-r)(1-b)(1-y) = 1 - r - b - y + rb + ry + by -ryb$ we have 8 components. Also we have 8 components white[i], red[i], orange[i], yellow[i], ... so you can make it a matrix multiplication and add the values of the resulting vector to obtain $r$ (when $i=1$). Now to make an inverse matrix we need more information about the resulting vector. If we just add everything that is in the vector, we lose that information. I still think it is possible to do it with a matrix, but i dont know how to create one, other than making some assumptions like $\text{white}[i]=[1,1,1]$ (which i think will be for inverse as well), and explain why that would be true.

-
Hi Carlo. Thank your for your reply! I think that the assumption with white[i] = [1,1,1] is true. I can't proove it, but in that case how should the solution look like. Partially I understand what you are suggesting, but if you can explain it a little bit more detailed I'll really appreciate it! Thank you! – Tamás Pap Feb 16 '13 at 12:22