Converting an rgb triple to a quaternion

300 Views Asked by At

I want to convert an rgb color triplet to a quaternion w + x*i + y*j + z*k. I thought of it as of rotation, and (using axis-angle representation and Euclidian length of a unit quaternion equals 1) I came to following equation system: \begin{align*} w &= \sqrt(1-(x^2+y^2+z^2))\\ w &= \cos(\arcsin(r/x))\\ w &= \cos(\arcsin(g/y))\\ w &= \cos(\arcsin(b/z)). \end{align*}

Here $r, g, b$ are constants and i need to obtain $x, y, z, w$.

I am a bit stumped. On the one hand there are 4 variables and 4 equations. On the other hand... how can I solve this? Could this even be solved?

2

There are 2 best solutions below

2
On BEST ANSWER

First of all, $\cos(\arcsin(x)) = \sqrt{1-x^2}$. So you can rewrite your latter three equations as $$w^2 = 1 - r^2/x^2 = 1-g^2/y^2 = 1-b^2/z^2.$$ Moreover from these equations, observe that if $x = \alpha r$ for some proportionality constant $\alpha$, then you also have that $ y= \alpha g$ and $z = \alpha b$. Substituting into the first equation gives $$w^2 = 1 - \alpha^2(r^2+g^2+b^2)$$ and from the second equation $$w^2 = 1 - \frac{1}{\alpha^2}$$ so we have that $$\alpha = \frac{1}{(r^2+g^2+b^2)^{1/4}}.$$ Plugging this in to the above equations gives you $x,y,z,w$ in terms of $r,g,b$.

0
On

Thank you! I've finally managed got working glsl code, due to your effort. I understand, this is not programmers forum, but for those who eventually will need this i could post (because i wrecked my head before i got correct result):

// converts vec3 color to vec4 quaternion
vec4 c2q( in vec3 c ) {
    c = c / sqrt3; // length(c) must be <= 1.0
    float rr = c.r*c.r;
    float gg = c.g*c.g;
    float bb = c.b*c.b;
    float ww = 1.0 - sqrt(rr+gg+bb);
    float xx = rr/(ww+1.0);
    float yy = gg/(ww+1.0);
    float zz = bb/(ww+1.0);
    return vec4( sqrt( xx ), sqrt( yy ), sqrt( zz ), sqrt( ww ) );
}

// converts vec4 quaternion to vec3 color
vec3 q2c( in vec4 q ) {
    float xx = q.x*q.x;
    float yy = q.y*q.y;
    float zz = q.z*q.z;
    float ww = q.w*q.w;
    float rr = (1.0-ww)*xx;
    float gg = (1.0-ww)*yy;
    float bb = (1.0-ww)*zz;
    vec3 c = vec3( sqrt( rr ), sqrt( gg ), sqrt( bb ) );
    return c * sqrt3; // renormalize
}

You could watch my working demo of rotation video image along white axis. Feel free to edit and experiment if you like ;-)