I love the smell of UnrealEd crashing in the morning. – tarquin

Difference between revisions of "HSV-RGB Conversion"

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search
(Created page with 'HSV is a way of representing a color. It is used in UEd's [http://udn.epicgames.com/Three/ColorPicker.html color picker], but there are no functions exp…')
 
m (added category so this orphan page can be reached from somewhere)
Line 1: Line 1:
[[Wikipedia:HSL_and_HSV|HSV]] is a way of representing a color. It is used in UEd's [http://udn.epicgames.com/Three/ColorPicker.html color picker], but there are no functions exposed to UScript for handling colors in this form. HSV is useful though, so here are some functions for converting between HSV and RGB.
+
[[wp:HSL and HSV|HSV]] is a way of representing a color. It is used in UEd's [[udn3:ColorPicker|color picker]], but there are no functions exposed to UScript for handling colors in this form. HSV is useful though, so here are some functions for converting between HSV and RGB.
  
 
==Struct==
 
==Struct==
First a struct for containing the HSV color, equivalent to the [[UE3:Object_structs_%28UT3%29#LinearColor|LinearColor]] struct for RGB colors.
+
First a struct for containing the HSV color, equivalent to the [[UE3:Object structs (UT3)#LinearColor|LinearColor]] struct for RGB colors.
 
<uscript>
 
<uscript>
 
/**
 
/**
Line 135: Line 135:
  
 
==Example Use==
 
==Example Use==
HSV is useful because it allows colours to be manipulated in a way that better fits the way we think. For instance, it's quite common to want several colours that differ only in hue, like [[UE3:HUD_%28UDK%29#GetRYGColorRamp|this HUD function]] which returns a colour that fades from red to green when passed a value from 0 to 1.
+
HSV is useful because it allows colours to be manipulated in a way that better fits the way we think. For instance, it's quite common to want several colours that differ only in hue, like [[UE3:HUD (UDK)#GetRYGColorRamp|this HUD function]] which returns a colour that fades from red to green when passed a value from 0 to 1.
 
<uscript>
 
<uscript>
 
/* returns Red (0.f) -> Yellow -> Green (1.f) Color Ramp */
 
/* returns Red (0.f) -> Yellow -> Green (1.f) Color Ramp */
Line 180: Line 180:
 
</uscript>
 
</uscript>
 
Much simpler.
 
Much simpler.
 +
 +
[[Category:Programming articles]]

Revision as of 14:24, 10 May 2010

HSV is a way of representing a color. It is used in UEd's color picker, but there are no functions exposed to UScript for handling colors in this form. HSV is useful though, so here are some functions for converting between HSV and RGB.

Struct

First a struct for containing the HSV color, equivalent to the LinearColor struct for RGB colors.

/**
 * A color represented by the four components Hue, Saturation, Value, and Alpha.
 * H must be between 0 and 360 (degrees).
 * S must be between 0 and 1.
 * V and A are normally between 0 and 1, but may exceed that range to give bloom.
 */
struct HSVColor
{
	var() float H, S, V, A;
 
	structdefaultproperties
	{
		A=1.0
	}
};

RGB to HSV

/**
 * Converts an RGB color to an HSV color, according to the algorithm described at http://en.wikipedia.org/wiki/HSL_and_HSV
 *
 * @param RGB the color to convert.
 * @return the HSV representation of the color.
 */
static final function HSVColor RGBToHSV(const out LinearColor RGB)
{
	local float Max;
	local float Min;
	local float Chroma;
	local HSVColor HSV;
 
	Min = FMin(FMin(RGB.R, RGB.G), RGB.B);
	Max = FMax(FMax(RGB.R, RGB.G), RGB.B);
	Chroma = Max - Min;
 
	//If Chroma is 0, then S is 0 by definition, and H is undefined but 0 by convention.
	if(Chroma != 0)
	{
		if(RGB.R == Max)
		{
			HSV.H = (RGB.G - RGB.B) / Chroma;
 
			if(HSV.H < 0.0)
			{
				HSV.H += 6.0;
			}
		}
		else if(RGB.G == Max)
		{
			HSV.H = ((RGB.B - RGB.R) / Chroma) + 2.0;
		}
		else //RGB.B == Max
		{
			HSV.H = ((RGB.R - RGB.G) / Chroma) + 4.0;
		}
 
		HSV.H *= 60.0;
		HSV.S = Chroma / Max;
	}
 
	HSV.V = Max;
	HSV.A = RGB.A;
 
	return HSV;
}

HSV to RGB

/**
 * Converts an HSV color to an RGB color, according to the algorithm described at http://en.wikipedia.org/wiki/HSL_and_HSV
 *
 * @param HSV the color to convert.
 * @return the RGB representation of the color.
 */
static final function LinearColor HSVToRGB(const out HSVColor HSV)
{
	local float Min;
	local float Chroma;
	local float Hdash;
	local float X;
	local LinearColor RGB;
 
	Chroma = HSV.S * HSV.V;
	Hdash = HSV.H / 60.0;
	X = Chroma * (1.0 - Abs((Hdash % 2.0) - 1.0));
 
	if(Hdash < 1.0)
	{
		RGB.R = Chroma;
		RGB.G = X;
	}
	else if(Hdash < 2.0)
	{
		RGB.R = X;
		RGB.G = Chroma;
	}
	else if(Hdash < 3.0)
	{
		RGB.G = Chroma;
		RGB.B = X;
	}
	else if(Hdash < 4.0)
	{
		RGB.G= X;
		RGB.B = Chroma;
	}
	else if(Hdash < 5.0)
	{
		RGB.R = X;
		RGB.B = Chroma;
	}
	else if(Hdash < 6.0)
	{
		RGB.R = Chroma;
		RGB.B = X;
	}
 
	Min = HSV.V - Chroma;
 
	RGB.R += Min;
	RGB.G += Min;
	RGB.B += Min;
	RGB.A = HSV.A;
 
	return RGB;
}

Example Use

HSV is useful because it allows colours to be manipulated in a way that better fits the way we think. For instance, it's quite common to want several colours that differ only in hue, like this HUD function which returns a colour that fades from red to green when passed a value from 0 to 1.

/* returns Red (0.f) -> Yellow -> Green (1.f) Color Ramp */
static function Color GetRYGColorRamp( float Pct )
{
	local Color GYRColor;
 
	GYRColor.A = 255;
 
	if ( Pct < 0.34 )
	{
    	GYRColor.R = 128 + 127 * FClamp(3.f*Pct, 0.f, 1.f);
		GYRColor.G = 0;
		GYRColor.B = 0;
	}
    else if ( Pct < 0.67 )
	{
    	GYRColor.R = 255;
		GYRColor.G = 255 * FClamp(3.f*(Pct-0.33), 0.f, 1.f);
		GYRColor.B = 0;
	}
    else
	{
		GYRColor.R = 255 * FClamp(3.f*(1.f-Pct), 0.f, 1.f);
		GYRColor.G = 255;
		GYRColor.B = 0;
	}
 
	return GYRColor;
}

As you can see, working in RGB results in relatively convoluted code for performing a simple task. Compare this to the equivalent using HSV

static function HSVColor GetRYGColorRampHSV(float Pct)
{
	local HSVColor HSV;
 
	HSV.H = 120.0 * FClamp(Pct, 0.0, 1.0); //0 is red, 60 is yellow, 120 is green.
	HSV.S = 1.0;
	HSV.V = 1.0;
 
	return HSVColor;
}

Much simpler.