Game Development Community

dev|Pro Game Development Curriculum

Converting HSV to RGB color space in Torquescript

by Conor O Kane · 05/07/2008 (5:32 am) · 2 comments

Here are some torquescript functions to convert colors between RGB and HSV color space. This is useful if you want to change the hue of a graphic while retaining its saturation and brightness.

function HSVtoRGB(%hsv)
{
   // *****************************
   // Takes a HSV string with values from 0 to 1 and returns RGB string.
   // This is not a perfect conversion, it's based on this algorithm - http://www.tecgraf.puc-rio.br/~mgattass/color/HSVtoRGB.htm
   // For a more accurate conversion use the algorithm shown here - http://www.mandelbrot-dazibao.com/HSV/HSV.htm
   // Conor O'Kane 2008, cokane.com
   // *****************************
    
   %h = getWord(%hsv, 0);
   %s = getWord(%hsv, 1);
   %v = getWord(%hsv, 2);
        
   if (%s == 0)
   {
       %r = %v;
       %g = %v;
       %b = %v;
   }
   else
   {
       %var_h = %h * 6;
       %var_i = mFloor(%var_h);
       %var_1 = %v * (1 - %s);
       %var_2 = %v * (1 - %s * (%var_h - %var_i));
       %var_3 = %v * (1 - %s * (1 - (%var_h - %var_i)));
        
       switch (%var_i)
       {
           case 0:
               %r = %v;
               %g = %var_3;
               %b = %var_1;
           case 1:
               %r = %var_2;
               %g = %v;
               %b = %var_3;
           case 2:
               %r = %var_1;
               %g = %v;
               %b = %var_3;
           case 3:
               %r = %var_1;
               %g = %var_2;
               %b = %v;
           case 4:
               %r = %var_3;
               %g = %var_1;
               %b = %v;
           case 5:
               %r = %v;
               %g = %var_1;
               %b = %var_2;
       }
   }
    
   return(%r @ " " @ %g @ " " @ %b);
}

function RGBtoHSV(%rgb)
{
   // *****************************
   // Takes an RGB string with values from 0 to 1 and returns HSV values from 0 to 1 as a space seperated string.
   // Based on this code - http://www.mandelbrot-dazibao.com/HSV/HSV.htm
   // Conor O'Kane 2008, cokane.com
   // *****************************
    
   %r = getWord(%rgb, 0);
   %g = getWord(%rgb, 1);
   %b = getWord(%rgb, 2);
        
   %var_Min = minimum3(%r, %g, %b);
   %var_Max = maximum3(%r, %g, %b);
   %del_Max = %var_Max - %var_Min;    // Delta RGB Value
    
   %v = %var_Max;
    
   if (%del_Max == 0)
   {
       %h = 0;
       %s = 0;
   }
   else
   {
       %del_R = (((%var_Max - %r) / 6) + (%del_Max / 2)) / %del_Max;
       %del_G = (((%var_Max - %g) / 6) + (%del_Max / 2)) / %del_Max;
       %del_B = (((%var_Max - %b) / 6) + (%del_Max / 2)) / %del_Max;
        
       %s = %del_Max / %var_Max;
       
       if (%r == %var_Max)
           %h = %del_B - %del_G;
       else if (%g == %var_Max)
           %h = (1 / 3) + %del_R - %del_B;
       else if (%b == %var_Max)
           %h = (2 / 3) + %del_G - %del_R;
            
       if (%h < 0)
           %h += 1;
       else if (%h > 1)
           %h -= 1;
   }
    
   return (%h @ " " @ %s @ " " @ %v);
}

function minimum3(%a, %b, %c)
{
   // needed by RGBtoHSV
   
   if (%a < %b)
       %min = %a;
   else
       %min = %b;
       
   if (%c < %min)
       %min = %c;
        
   return(%min);
}

function maximum3(%a, %b, %c)
{
   // needed by RGBtoHSV
   
   if (%a > %b)
       %max = %a;
   else
       %max = %b;
       
   if (%c > %max)
       %max = %c;
        
   return(%max);
}

And here's a function that uses the conversions to rotate the hue of an object:

function rotateHue(%object, %angle)
{
   // *****************************
   // Takes an object and rotates its hue by the angle
   // Full hue rotation is 360 degrees
   // Conor O'Kane 2008, cokane.com
   // *****************************

   %rgba = %object.getBlendColor();
	
   %rgb = getWords(%rgba, 0, 2);
   %alpha = getWord(%rgba, 3);
    
   %hsv = RGBtoHSV(%rgb);
   %trueAngle = %angle / 360;
   %h = getWord(%hsv, 0);
   %hueRotated = %h + %trueAngle;
    
   if (%hueRotated < 0)
       %hueRotated += 1;
   else if (%hueRotated > 1)
       %hueRotated -= 1;
        
   %hsv = setWord(%hsv, 0, %hueRotated);
   %rgb = HSVtoRGB(%hsv);
   %rgba = (%rgb @ " " @ %alpha);
            
   %object.setBlendColor(%rgba);   
}

Note that the HSVtoRGB function is slightly lossy due to rounding, so errors will accumulate if you repeatedly switch from RGB to HSV and back in a loop. This will cause the colors to desaturate eventually. To avoid this, store the object's original RGB values and always modify the hue from those base values, rather than its current RGB color.

#2
05/07/2008 (10:51 am)
http://beesbuzz.biz/code/hsv_color_transforms.php

Check out that page for how to do HSV rotations using matrix transforms. (Hooray for systems of linear equations)