1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2026-01-01 01:41:18 +01:00

sys/color: fix rgb2hsv function

This commit is contained in:
Karl Fessel 2023-05-31 20:49:57 +02:00
parent 8f8e29d9bd
commit 19a194c4a8

View File

@ -27,54 +27,74 @@
void color_rgb2hsv(color_rgb_t *rgb, color_hsv_t *hsv)
{
float rd, gd, bd, delta;
float rd, gd, bd, delta, min, max;
int imax, imin, sector;
/* norm RGB colors to the range [0 - 1.0] */
rd = (float)rgb->r / 255.0f;
gd = (float)rgb->g / 255.0f;
bd = (float)rgb->b / 255.0f;
/* find value as maximum of the three colors */
if (rd >= gd) {
hsv->v = (rd >= bd) ? rd : bd;
}
else {
hsv->v = (gd >= bd) ? gd : bd;
/* catch special case grey first */
if (rgb->r == rgb->g && rgb->r == rgb->b) {
hsv->v = (float)rgb->r * (1 / 255.0f);
hsv->s = 0.0f;
hsv->h = 0.0f; /* hue might be anything for grey, but it is not uncommon to use 0 */
return;
}
/* compute delta from value and minimum of the three RGB colors */
if (rd <= gd) {
delta = (rd <= bd) ? (hsv->v - rd) : (hsv->v - bd);
/* normalize RGB colors to the range [0 - 1.0] */
/* multiplication is often faster than division -> using compile time constant */
rd = (float)rgb->r * (1 / 255.0f);
gd = (float)rgb->g * (1 / 255.0f);
bd = (float)rgb->b * (1 / 255.0f);
/* find maximum of the three colors and sector */
/* using the comparing faster integer color value */
imax = rgb->r;
max = rd;
sector = 0;
if (rgb->g > imax) {
imax = rgb->g;
max = gd;
sector = 1;
}
else {
delta = (gd <= bd) ? (hsv->v - gd) : (hsv->v - bd);
if (rgb->b > imax) {
imax = rgb->b;
max = bd;
sector = 2;
}
/* value is maximum*/
hsv->v = max;
/* find of minimum the three RGB colors */
imin = rgb->r;
min = rd;
if (rgb->g < imin) {
imin = rgb->g;
min = gd;
}
if (rgb->b < imin) {
imin = rgb->b;
min = bd;
}
/* compute delta from value and minimum*/
delta = hsv->v - min;
/* find the saturation from value and delta */
hsv->s = (hsv->v != 0.0f) ? (delta / hsv->v) : 0.0f;
/* special case gray r == g == b ^= min == max */
hsv->s = delta / max;
/* compute hue */
hsv->h = 0.0f;
if (hsv->s != 0.0f) {
float rc, gc, bc;
rc = (hsv->v - rd) / delta;
gc = (hsv->v - gd) / delta;
bc = (hsv->v - bd) / delta;
if (rd == hsv->v) {
hsv->h = bc - gc;
}
else if (gd == hsv->v) {
hsv->h = 2.0f + rc - bc;
}
else {
hsv->h = 4.0f + gc - rc;
}
hsv->h *= 60.0f;
if (hsv->h < 0.0f) {
hsv->h += 360.0f;
}
float p = 60.0f / delta;
switch (sector){
case 0:
hsv->h = (gd - bd) * p;
break;
case 1:
hsv->h = 120.0f + (bd - rd) * p;
break;
case 2:
hsv->h = 240.0f + (rd - gd) * p;
break;
}
if (hsv->h < 0.0f) {
hsv->h += 360.0f;
}
}