HSV HSL与RGB转换

本文详细介绍RGB、HSV及HSL色彩空间之间的相互转换方法,并提供C语言实现代码。通过具体实例展示了不同色彩空间的特点及其应用场景。

算法公式请参考:转换公式
转换工具请参考:在线转换

下方代码可直接编译测试

#include <stdio.h>

// #define     RAND_MAX_ONE        //h:0-360   s:0-1   v:0-1	非百分比
#define     RAND_MAX_HUNDRED    //h:0-360   s:0-100 v:0-100		百分比
#define		MAX(R,G,B)		(((R)>(G))?(((R)>(B))?(R):(B)):(((G)>(B))?(G):(B)))
#define		MIN(R,G,B)		(((R)<(G))?(((R)<(B))?(R):(B)):(((G)<(B))?(G):(B)))

typedef struct{
	double h;
	double s;
	double v;
}hsv_t;


typedef struct{
	double h;
	double s;
	double l;
}hsl_t;


typedef struct{
	unsigned char r;
	unsigned char g;
	unsigned char b;
}rgb_t;


/*
 * @brief RGB -> HSV
 *
 * @param [in] rgb		输入参数rgb
 * @param [in] hsv		输出参数hsv
 *
 * @return None
 */
void rgb_2_hsv(hsv_t *hsv,rgb_t *rgb)
{
	double rr,gg,bb;
	double max,min,des;

	rr = (double)rgb->r;
	gg = (double)rgb->g;
	bb = (double)rgb->b;

	max = MAX(rr,gg,bb);
	min = MIN(rr,gg,bb);
	des = max - min;

	if(des != 0)							//max != min
	{
		if(rr == max)
		{
			hsv->h = (gg-bb)/des;
		}
		else if(gg == max)
		{
			hsv->h = (bb - rr)/des + 2;
		}
		else if(bb == max)
		{
			hsv->h = (rr - gg)/des + 4;
		}
		#if defined RAND_MAX_ONE
		hsv->s = des / max;
		#elif defined RAND_MAX_HUNDRED
		hsv->s = des / max * 100;
		#endif
	}
	else if(max != 0)						//max=min && max!=0
	{
	#if defined	RAND_MAX_ONE
		hsv->s = des / max;
	#elif defined RAND_MAX_HUNDRED
		hsv->s = des / max *100;
	#endif
	}
	else									//max=min && max=0
	{
		hsv->h = hsv->s = 0;
	}

	hsv->h *= 60;

	if(hsv->h < 0)
	{
		hsv->h += 360;
	}

#if defined	RAND_MAX_ONE
	hsv->v = max / 255.0f;
#elif defined RAND_MAX_HUNDRED
	hsv->v = max / 255.0f * 100;
#endif
}


/*
 * @brief HSV -> RGB
 *
 * @param [in] hsv		输入参数hsv
 * @param [in] rgb		输出参数rgb
 *
 * @return None
 */
void hsv_2_rgb(hsv_t *hsv,rgb_t *rgb)
{
    int i = ((int)(hsv->h/60)%6);
	double f = hsv->h/60 - i;
	double r,g,b,p,q,t,v,s;

#if defined RAND_MAX_ONE
    v = hsv->v;
    s = hsv->s;
#elif defined   RAND_MAX_HUNDRED
    v = hsv->v / 100;
    s = hsv->s / 100;
#endif
    p = v * (1 - s);
	q = v * (1 - f * s);
	t = v * (1 - (1 - f) * s);

	switch(i)
	{
		case	0:	r = v; g = t; b = p;	break;

		case	1:	r = q; g = v; b = p;	break;

		case	2:	r = p; g = v; b = t;	break;

		case	3:	r = p; g = q; b = v;	break;

		case	4:	r = t; g = p; b = v;	break;

		case	5:	r = v; g = p; b = q;	break;

		default:
				break;
	}

    rgb->r = r * 255;
    rgb->g = g * 255;
    rgb->b = b * 255;
}


/*
 * @brief RGB -> HSL
 *
 * @param [in] rgb		输入参数rgb
 * @param [in] hsl		输出参数hsl
 *
 * @return None
 */
void rgb_2_hsl(hsl_t *hsl,rgb_t *rgb)
{
	double rr,gg,bb;
	double max,min,des;

	rr = (double)rgb->r;
	gg = (double)rgb->g;
	bb = (double)rgb->b;

	max = MAX(rr,gg,bb);
	min = MIN(rr,gg,bb);
	des = max - min;

	hsl->l = (max + min) / 2 / 255.0f;

	if(des != 0)							//max != min
	{
		if(rr == max)
		{
			hsl->h = (gg-bb)/des;
		}
		else if(gg == max)
		{
			hsl->h = (bb - rr)/des + 2;
		}
		else if(bb == max)
		{
			hsl->h = (rr - gg)/des + 4;
		}

		if(hsl->l <= 0.5)
		{
			hsl->s = des / (2 * hsl->l) / 255.0f;
		}
		else
		{
			hsl->s = des / (2 - (2 * hsl->l)) / 255.0f;
		}
	}
	else									//max=min
	{
		hsl->h = hsl->s = 0;
	}

	hsl->h *= 60;

	if(hsl->h < 0)
	{
		hsl->h += 360;
	}

#if defined RAND_MAX_HUNDRED
	hsl->s *= 100;
	hsl->l *= 100;
#endif
}


/*
 * @brief HSL转RGB
 *
 * @param [in] temp1	输入参数r,g,b
 * @param [in] temp2	输入参数p
 * @param [in] temp3	输入参数q
 *
 * @return None
 */
void hsl_2_rgb_value(double *temp1,double *temp2,double *temp3)
{
	if(*temp1 < 0)
	{
		*temp1 += 1.0;
	}
	else if(*temp1 > 1)
	{
		*temp1 -= 1.0;
	}

	if(*temp1*6.0 < 1.0)
	{
		*temp1 = *temp2 + ((*temp3 - *temp2) * 6 * (*temp1));
	}
	else if(*temp1 * 2.0 < 1.0)
	{
		*temp1 = *temp3;
	}
	else if(*temp1 * 3.0 < 2)
	{
		*temp1 = *temp2 + ((*temp3- *temp2) * 6 * ((2 / 3) - *temp1));
	}
	else
	{
		*temp1 = *temp2;
	}
}


/*
 * @brief HSL -> RGB
 *
 * @param [in] hsl		输入参数hsl
 * @param [in] rgb		输出参数rgb
 *
 * @return None
 */
void hsl_2_rgb(hsl_t *hsl,rgb_t *rgb)
{
	double q,p,h,l,s,r,g,b;

#if defined RAND_MAX_ONE
	l = hsl->l;
	s = hsl->s;
#elif defined RAND_MAX_HUNDRED
	l = hsl->l / 100;
	s = hsl->s / 100;
#endif

	if(s == 0)
	{
		rgb->r = rgb->g = rgb->b = l * 255;
	}
	else
	{
		if(l < 0.5)
		{
			q = l * (1 + s);
		}
		else
		{
			q = l + s - (l * s);
		}

		p = 2 * l - q;

		h = hsl->h / 360;				//h规范化到[0,1]内
		r = h + (1.0 / 3.0);
		g = h;
		b = h - (1.0 / 3.0);

		hsl_2_rgb_value(&r,&p,&q);
		hsl_2_rgb_value(&g,&p,&q);
		hsl_2_rgb_value(&b,&p,&q);

		rgb->r = r * 255;
		rgb->g = g * 255;
		rgb->b = b * 255;
	}
}


int main()
{
	rgb_t rgbTemp = {255,255,255};
	hsv_t hsvTemp = {0};
	hsl_t hslTemp = {0};

	rgb_2_hsv(&hsvTemp,&rgbTemp);
	printf("%f %f %f\n",hsvTemp.h,hsvTemp.s,hsvTemp.v);
	
	hsv_2_rgb(&hsvTemp,&rgbTemp);
	printf("%d %d %d\n",rgbTemp.r,rgbTemp.g,rgbTemp.b);

	rgb_2_hsl(&hslTemp,&rgbTemp);
	printf("%f %f %f\n",hslTemp.h,hslTemp.s,hslTemp.l);
	
	hsl_2_rgb(&hslTemp,&rgbTemp);
	printf("%d %d %d\n",rgbTemp.r,rgbTemp.g,rgbTemp.b);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值