1. 程式人生 > >數字影象處理 顏色空間RGB、HSI、CMYK、YUV的相互轉換

數字影象處理 顏色空間RGB、HSI、CMYK、YUV的相互轉換

//================================================================================
/// @brief HLS <====> RGB
///
/// [1]H是色相,代表了6種顏色,分成0~6區域,用一個模型來表述就是一個雙(六)稜椎,其中的L是HSL立方體的主對角線。
//     RGB立方體的頂點:紅、黃、綠、青、藍和品紅就成為HSL六角形的頂點,0-360度的範圍內有6種顏色,但是它不是平均分佈的,如綠色最多.
///    H是0-360,L和S是0.00%-100.00%  
//================================================================================
//HLS ---> RGB
void RGBtoHLS (int rgb, double& H, double& L, double& S)
{
	Color color(rgb);
	RGBtoHLS(color.R, color.G, color.B, H, L, S);
}

//HLS ---> RGB
void RGBtoHLS (int r, int g, int b, double& H, double& L, double& S)
{
	int   n_cmax = max(r, max(g, b));
	int   n_cmin = min(r, min(g, b));

	double Delta = 0;
	double Max = 0, Min = 0;
	double Redf = 0, Greenf = 0, Bluef = 0;

	Redf    = (r / 255.0f);
	Greenf  = (g / 255.0f);
	Bluef   = (b / 255.0f); 

	Max     = max(max(Redf, Greenf), Bluef);
	Min     = min(min(Redf, Greenf), Bluef);

	H = 0;
	L = (Max + Min) / 2.0f;
	S = 0;

	if (Max == Min)
	{
		return;
	}

	Delta = (Max - Min);
	if (L < 0.5)
		S = Delta / (Max + Min);
	else
		S = Delta / (2.0 - Max - Min);

	if (Redf == Max)
	{
		if (Greenf >= Bluef)
		{
			H = (Greenf - Bluef) / Delta;
		}
		else
		{
			H = 6.0 + (Greenf - Bluef) / Delta;
		}
	}		
	else if (Greenf == Max)
		H = 2.0 + (Bluef - Redf) / Delta;
	else
		H = 4.0 + (Redf - Greenf) / Delta;

	H /= 6.0; //除以6,表示在那個部分。

	if (H < 0.0)
		H += 1.0;   
	if (H > 1)
		H -= 1;

	H = (int)(H * 360); //轉成[0, 360]
}

void Color_HueToRgb(double p, double q, double Ht, double *Channel)
{
	if (Ht < 0.0)
		Ht += 1.0;
	else if (Ht > 1.0)
		Ht -= 1.0;

	if ((6.0 * Ht) < 1.0)
		*Channel = (p + (q - p) * Ht * 6.0);
	else if ((2.0 * Ht) < 1.0)
		*Channel = (q);
	else if ((3.0 * Ht) < 2.0)
		*Channel = (p + (q - p) * ((2.0F / 3.0F) - Ht) * 6.0);
	else
		*Channel = (p);
}

//RGB ---> HLS
void HLStoRGB (double H, double L, double S, BYTE &r, BYTE &g, BYTE &b)
{
	double M1 = 0, M2 = 0;
	double Redf = 0, Greenf = 0, Bluef = 0;

	double hue = H / 360;

	if (S == 0)//灰色
	{
		Redf    = L;
		Greenf  = L;
		Bluef   = L;
	}
	else
	{
		if (L <= 0.5)
			M2 = L * (1.0 + S);
		else
			M2 = L + S - L * S;

		M1 = (2.0 * L - M2);

		Color_HueToRgb(M1, M2, hue + (1.0F / 3.0F), &Redf);
		Color_HueToRgb(M1, M2, hue, &Greenf);
		Color_HueToRgb(M1, M2, hue - (1.0F / 3.0F), &Bluef);
	}

	r = (BYTE)(Redf * 255);
	g = (BYTE)(Bluef * 255);
	b = (BYTE)(Greenf * 255);
}