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 the article – Paint Inspired Color Mixing and Compositing for Visualization.
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.
Best Answer
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!