Color Space Conversions

From XNAWiki
Jump to: navigation, search

The following are conversions between various color spaces.

RGB-XYZ

#ifndef CONVERT_XYZ_RGB
#define CONVERT_XYZ_RGB
 
float3 XYZ_to_RGB(float3 XYZ)
{
	static float3x3 XYZ_to_sRGB =
	{
		 3.240479, -0.969256,  0.055648,
		-1.537150,  1.875991, -0.204043,
		-0.498535,  0.041556,  1.057311
	};
	return mul(XYZ, XYZ_to_sRGB);
}
 
float3 RGB_to_XYZ(float3 sRGB)
{
	static float3x3 sRGB_to_XYZ = 
	{
		0.4124564, 0.2126729, 0.0193339,
		0.3575761, 0.7151522, 0.1191920,
		0.1804375, 0.0721750, 0.9503041
	};
	return mul(sRGB, sRGB_to_XYZ);
}
 
#endif

RGB-xyY

#ifndef CONVERT_xyY_RGB
#define CONVERT_xyY_RGB
 
float3 xyY_to_RGB(float3 xyY)
{
	xyY.y = max(1e-6, xyY.y);
 
	float3 XYZ;
	XYZ.x = xyY.x * (xyY.z / xyY.y);
	XYZ.y = xyY.z;
	XYZ.z = (1 - xyY.x - xyY.y) * (xyY.z / xyY.y);
	return XYZ_to_RGB(XYZ);
}
 
float3 RGB_to_xyY(float3 sRGB)
{
	float3 XYZ = RGB_to_XYZ(sRGB);
	float sum = max(1e-6, XYZ.x + XYZ.y + XYZ.z);
 
	float3 result;
	result.x = XYZ.x / sum;
	result.y = XYZ.y / sum;
	result.z = XYZ.y;
	return result;
}
#endif

RGB-Hue

  • Note: this may not compile properly on all versions of the effect compiler, works fine on fxc fx_2_0 profile.
#ifndef CONVERT_HUE_RGB
#define CONVERT_HUE_RGB
 
float3 Hue_to_RGB(float H, float C)
{
	float Hn = ((H * 360) / 60) % 6;
	float X = C * (1 - abs((Hn % 2) - 1));
 
	float3 hlu[] =
	{
		C, X, 0,	// 0
		X, C, 0,	// 1
		0, C, X,	// 2
		0, X, C,	// 3
		X, 0, C,	// 4
		C, 0, X		// 5
	};
	int i = floor(Hn);
 
	return hlu[i];
}
float RGB_to_Hue(float3 color)
{
	float M = max(max(color.r, color.g), color.b);
	float m = min(min(color.r, color.g), color.b);
	float C = M - m;
 
	float invC = 1 / max(C, 1e-6);
 
	int i = abs((2 * (M == color.b)) - (M == color.g)) * (M != color.r);
	float4 hlu = color.gbrg;
 
	float Hn = ((hlu[i] - hlu[i + 1])) * invC;
	float Hp = (2 * i) + ((M == color.r && color.g < color.b) * 6);
 
	return (Hn + Hp) / 6;
}
 
#endif

RGB-HSL

#ifndef CONVERT_HSL_RGB
#define CONVERT_HSL_RGB
 
float3 HSL_to_RGB(float3 hsl)
{
	float C = (1 - abs(2 * hsl.b - 1)) * hsl.g;
	float m = hsl.b - (0.5 * C);
 
	return Hue_to_RGB(hsl.r, C) + m;
}
float3 RGB_to_HSL(float3 color)
{
	float M = max(max(color.r, color.g), color.b);
	float m = min(min(color.r, color.g), color.b);
	float C = M - m;
 
	float L = 0.5 * (M + m);
	float S = C / max(abs((2 * (L > 0.5)) - (2 * L)), 1e-6);
	float H = RGB_to_Hue(color);
 
	return float3(H, S, L);
}
 
#endif

RGB-HSV

#ifndef CONVERT_HSV_RGB
#define CONVERT_HSV_RGB
 
float3 HSV_to_RGB(float3 hsv)
{
	float C = hsv.b * hsv.g;
	float m = hsv.b - C;
	return Hue_to_RGB(hsv.r, C) + m;
}
float3 RGB_to_HSV(float3 color)
{
	float M = max(max(color.r, color.g), color.b);
	float m = min(min(color.r, color.g), color.b);
	float C = M - m;
 
	return float3(RGB_to_Hue(color), C / max(1e-6, M), M);
}
 
#endif