I am in a weird situation where I have to convert colors from a "white+green" color space to an RGB color space:

$$(w,g)\rightarrow(R,G,B)\\\ w,g,R,G,B\in[0,1]$$

Essentially, I have to take a "white" ($w$) and "green" ($g$) coordinate and map it to some point on the half of the $R=B$ plane where $G\geq{R}$ (image below is range, black triangle excluded):

enter image description here

I've come up with a list of four known mapped points. Since $R=B$ I'm going to refer to both as $R$. The constant $p\in(0,1)$ below is a value I can adjust to taste (sorry about incorrect notation):

$$ f:(w,g)\rightarrow(R,G)\\ f(0,0)\rightarrow(0,0)\\ f(1,0)\rightarrow(1,1)\\ f(1,1)\rightarrow(p,1)\\ f(0,1)\rightarrow(0,1) $$

Graphically, it looks like this:

enter image description here

I'm taking a square and deforming it to a triangle, where the bottom right point of the square becomes the top right point of the triangle, and the top right point of the square moves left along the top edge.

The dotted line should remain straight and the deformation of each half of the square (either side of dotted line) should be linear -- these are arbitrary choices but it seems to make sense for my situation, and is simpler to think about. If it over-complicates the math, though, it doesn't need to stay that way (sorry it's so ill-defined -- the nature of the problem has some subjective aspects).

My question is: I need help creating $f(w,g)$. I understand it well, graphically, but I can't really get my head around the actual math for some reason.

Sorry about all notation errors above, I'm not really a math guy, I'm just guessing.


You've got two triangles, and you want to map them linearly to two other triangles. So let's do that.

The upper left triangle, i.e. the $g > w$ case, is easy: the $g$ axis stays fixed, while the $w$ axis is simply scaled down by a factor of $p$, giving us the map $(w, g) \mapsto (pw, g)$.

The lower right triangle, where $g < w$, is slightly trickier. We can start by considering the case $p = 1$, where clearly the $g$ coordinate is squeezed out and the whole triangle simply mapped to the line $R = G = w$, giving us the degenerate map $(w, g) \mapsto (w, w)$. More generally, if $p < 1$, we'll still map the $w$ axis to that line, but we'll also have to subtract some multiple of $g$ from $R$ so that $(1,1)$ maps to $(p,1)$ instead of $(1,1)$. A bit of thinking shows that the correct scaling factor is $1-p$, giving us the map $(w, g) \mapsto (w - (1-p)g, w)$.

Putting these together, the full map is simply:

$$f(w,g) = \begin{cases} (p w, g) & \text{if } g > w \\ (w - (1-p)g, w) & \text{otherwise} \end{cases}$$

To make sure the resulting function is continuous, we can check that, on the boundary line $w = g$, the two pieces indeed join together:

$$w = g \implies w - (1-p)g = w - g + pg = pw$$

Ps. If you'd prefer something more systematic and generally applicable than the reasoning above, you can also derive these formulas using linear algebra.

The first step is to note that we're going to need a piecewise function composed of two linear (well, affine, actually) maps, one for each triangle. The second step to note is that any affine map $h: \mathbb R^2 \to \mathbb R$ can be written as:

$$h(x,y) = a + bx + cy$$

where $a$, $b$ and $c$ are constants. Since our output space is also two-dimensional, we're going to need two of these maps for each triangle, so that our final function will look like this:

$$f(w,g) = \begin{cases} (a_{11} + b_{11}w + c_{11}g,\, a_{12} + b_{12}w + c_{12}g) & \text{if } (w, g) \in \text{triangle 1} \\ (a_{21} + b_{21}w + c_{21}g,\, a_{22} + b_{22}w + c_{22}g) & \text{if } (w, g) \in \text{triangle 2} \end{cases}$$

Now, given the corner points of the original and mapped triangles, we can find the coefficients $a$, $b$ and $c$ for each triangle and each output coordinate by solving the system of three linear equations:

$$\begin{aligned} Z_1 &= a + bw_1 + cg_1 \\ Z_2 &= a + bw_2 + cg_2 \\ Z_3 &= a + bw_3 + cg_3 \end{aligned}$$

where $(w_i, g_i)$ are the original coordinates of each corner points, $(R_i, G_i)$ are the coordinates of the transformed corner points, and $Z_i$ stands for either $R_i$ or $G_i$ depending on which coordinate we're solving the coefficients for.

So, for example, for the second triangle we have the known corner points $(0,0) \mapsto (0,0)$, $(1,0) \mapsto (1,1)$ and $(1,1) \mapsto (p,1)$, giving us the following equations for the $R$ output coordinate:

$$\begin{aligned} 0 &= a_{21} + b_{21}\cdot0 + c_{21}\cdot0 \\ 1 &= a_{21} + b_{21}\cdot1 + c_{21}\cdot0 \\ p &= a_{21} + b_{21}\cdot1 + c_{21}\cdot1 \end{aligned}$$

You could solve this using e.g. Gaussian elimination, but in this case that would be overkill: it's obvious from the first equation that $a_{21} = 0$ and from the second equation that $b_{21} = 1$. Plugging those into the last equation then leaves us with $p = 1 + c_{21}$ and thus $c_{21} = p - 1$.

Repeating the process for the other three sets of coefficients is left as a simple exercise.

  • $\begingroup$ This is perfect! Thank you! I wish I could give a second +1 for your edit. I had to think a little about the scale factor point, but it makes complete sense to me now. Thanks again. $\endgroup$ – Jason C Mar 1 '14 at 23:03
  • 1
    $\begingroup$ I made another edit to the post, describing a more general method of finding such functions. You might find it useful if you need to do something like this again later. $\endgroup$ – Ilmari Karonen Mar 1 '14 at 23:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.