How does the formula of conversion HSV to RGB work?

Viewed 311

First of all, the code works but I want to understand how it works (each line).

Here my code of the interpolation :

void colortemp(float temp, FILE* tempfile)
{
    //float temp_min = -138.0;
    //float temp_max = -37.0;
    //float color_min = 240.0;
    //float color_max = 0;

    if(temp < 135.0f)
    {
        temp = 135.0f;
    }
    /*
    if(temp > 310.0f)
    {
        temp = 310.0f;
    }*/
    float a = ( 0.0f - 240.0f) / ( 310.0f - 135.0f);
    float b = 240.0f - (a * 135.0f);
    float h = (temp * a ) + b;

    float S = 1.0f, V = 1.0f; //HSV
    float P, Q, T, fract;

    unsigned char pix[3];

    (h == 360.0f)?(h = 0.0f):(h /= 60.0f); --> WHY DIVIDE BY 60, NO MODULO ?
    fract = h - floor(h);

    P = (V*(1. - S))*255;
    Q = (V*(1. - S*fract))*255;
    T = (V*(1. - S*(1. - fract)))*255;

    V*=255;
    S*=255;

    if (0. <= h && h < 1.) //WHY WE USE BETWEEN TWO VALUES AND NOT EQUALS TO 1 FOR EXAMPLE
    {
            pix[0] = (int)V;
            pix[1] = (int)T;
            pix[2] = (int)P;
    }

    else if (1. <= h && h < 2.)
    {
            pix[0] = (int)Q;
            pix[1] = (int)V;
            pix[2] = (int)P;
    }

    else if (2. <= h && h < 3.)
    {
            pix[0] = (int)P;
            pix[1] = (int)V;
            pix[2] = (int)T;
    }

    else if (3. <= h && h < 4.)
    {
            pix[0] = (int)P;
            pix[1] = (int)Q;
            pix[2] = (int)V;
    }

    else if (4. <= h && h < 5.)
    {
            pix[0] = (int)T;
            pix[1] = (int)P;
            pix[2] = (int)V;
    }

    else if (5. <= h && h < 6.)
    {
            pix[0] = (int)V;
            pix[1] = (int)P;
            pix[2] = (int)Q;
    }

    else
    {
            pix[0] = 153;
            pix[1] = 20;
            pix[2] = 0;
    }

    fwrite(pix,1,3,tempfile);
}

I took code from someone who posted on Stack Overflow and edited it. But I don't understand all things in the code.

Furthermore here in Wikipedia (it's in french, the t is the h for hue) it's different because we do a modulo 6 and we look if we are equals to 1,2,3 etc. and not if we are between 1 or 2 for example. enter image description here

If we look the algorithm in Wikipedia there are no explanations so I don't know how it works...

We have the hue, the variable h, we divide the hue by 60... why by 60?

Again in the algorithm in Wikipedia, we have a variable hi and we do a modulo 6 here why?

In my code, the guy who posted it does just : fract = h - floor(h) and not fract = h - (floor(h) mod 6)

If we continue we see 3 variables (in the algorithm in Wikipedia) l, m and n. These are temporary variables but how do we find the formulas that will give us the results of these variables?

And finally in my code the RGB is found if we are between two values and in the algorithm it's found if it is EQUAL to the value. Why is there a difference?

The code works but as you can see, I understand few things of the mathematics behind the conversion of the HSV to RGB. If someone can explain me please.

1 Answers

The h in HSV is an angle 0-359 degrees. The HSV to RGB transform is defined in 6 separate pieces based on which 60-degree sector h is in: with h between 0-59 it's defined one way, with h between 60-119 it's defined another way, with h between 120-179 it's defined a third way, and so on.

Therefore the first step of the process is finding which sector we're in. One way to do that is to divide h by 60, which gives you a value between 0 and 6 (exclusive). Taking the floor of that number would give an integer 0-5, which tells you the sector.

What if h isn't between 0-359, how do you determine the sector then? The Wikipedia article takes this into account: this is where you need the modulo operator. The c++ program does not handle this case: it assumes h is already in the correct range.

If we continue we see 3 variables (in the algorithm in Wikipedia) l, m and n. These are temporary variables but how do we find the formulas that will give us the results of these variables?

It's a trilinear interpolation that you can derive from the following rules:

  • value=0 should give black
  • saturation=0 should give gray: all color components are equal to "value"
  • saturation=1 should give a "fully saturated" color. A fully saturated color is one where the highest RGB component is equal to "value"
  • hue should interpolate between two color components while the third is a constant

To get a better understanding, try taking for example red color in HSV h=0 s=1 v=1 and see how changing each component h s and v affect the outcome.

And finally in my code the RGB is found if we are between two values and in the algorithm it's found if it is EQUAL to the value. Why is there a difference?

It's because the c++ program didn't bother to use the floor function back in step 1. Instead of h being an integer 0-5 it's a fraction 0-6 (exclusive)

Related