#include "stdint.h"
/*
* RGB HSL
* 255,255,255 0,0,255
* 0,255,255 128,255,128
* 128,255,255 128,255,192
* 0,0,255 170,255,128
* 0,128,255 149,255,128
* 0,0,0 0,0,0
* 0,0,128 170,255,64
*
*
* 42*r/255 =>
*
*
* */
typedef union
{
struct
{
uint8_t red; // [0,255]
uint8_t green; // [0,255]
uint8_t blue; // [0,255]
};
struct
{
uint8_t r; // [0,255]
uint8_t g; // [0,255]
uint8_t b; // [0,255]
};
} COLOR_RGB;
typedef union
{
struct
{
uint8_t hue; // [0,360] 色调
uint8_t saturation; // [0,_D_saturation_MAX] 饱和度
uint8_t luminance; // [0,_D_luminance_MAX] 亮度
};
struct
{
uint8_t h; // [0,360] 色调
uint8_t s; // [0,_D_saturation_MAX] 饱和度
uint8_t l; // [0,_D_luminance_MAX] 亮度
};
} COLOR_HSL;
typedef struct {
float r; // [0,255]
float g; // [0,255]
float b; // [0,255]
}ColorF;
#define _D_HUE_MAX (255.0)
#define _D_saturation_MAX (255.0)
#define _D_luminance_MAX (255.0)
#define min3v(v1, v2, v3) (v1<v2? (v1<v3? v1:(v2<v3? v2:v3)):(v2<v3? v2:v3))
#define max3v(v1, v2, v3) (v1<v2? (v2<v3? v3:v2):(v1<v3? v3:v1))
// Converts RGB to HSL
static COLOR_HSL rgb2hsl(/*[in]*/const COLOR_RGB rgb, /*[out]*/COLOR_HSL *hsl=0)
{
ColorF color={(float)rgb.r, (float)rgb.g, (float)rgb.b};
float h=0, s=0, l=0;
// normalizes red-green-blue values
float maxVal = 0;
float minVal = 0;
COLOR_HSL HSL;
const float bh = 1.0/6.0*_D_HUE_MAX;
color.r = ( color.r )/255.0f;
color.g = ( color.g )/255.0f;
color.b = ( color.b )/255.0f;
maxVal = max3v(color.r, color.g, color.b);
minVal = min3v(color.r, color.g, color.b);
// hue
if(maxVal == minVal)
{
h = 0; // undefined
}
else if(maxVal==color.r && color.g>=color.b)
{
h = bh*(color.g-color.b)/(maxVal-minVal);
}
else if(maxVal==color.r && color.g<color.b)
{
h = bh*(color.g-color.b)/(maxVal-minVal) + _D_HUE_MAX;
}
else if(maxVal==color.g)
{
h = bh*(color.b-color.r)/(maxVal-minVal) + 1.0/3.0*_D_HUE_MAX;
}
else if(maxVal==color.b)
{
h = bh*(color.r-color.g)/(maxVal-minVal) + 2.0/3.0*_D_HUE_MAX;
}
// luminance
l = (maxVal+minVal)/2.0f;
// saturation
if(l == 0 || maxVal == minVal)
{
s = 0.0;
}
else if(0<l && l<=0.5f)
{
s = (maxVal-minVal)/(maxVal+minVal);
}
else if(l>0.5f)
{
s = (maxVal-minVal)/(2.0 - (maxVal+minVal)); //(maxVal-minVal > 0)?
}
// qDebug(">> H=%f; S=%f; L=%f ", h, s, l );
HSL.h = ((h>_D_HUE_MAX)? _D_HUE_MAX : ((h<0)?0:h));
HSL.s = (((s>1)? 1 : ((s<0)?0:s))*_D_saturation_MAX);
HSL.l = (((l>1)? 1 : ((l<0)?0:l))*_D_luminance_MAX);
if(hsl!=0)
{
*hsl=HSL;
}
return HSL;
}
// Converts HSL to RGB
static COLOR_RGB hsl2rgb(const COLOR_HSL hsl, COLOR_RGB *rgb=0)
{
float h = hsl.h;// /255.0 * _D_HUE_MAX;
float s = hsl.s;// /255.0 * _D_saturation_MAX;
float l = hsl.l;// /255.0 * _D_luminance_MAX;
COLOR_RGB rgba;
ColorF color;
h = h; // h must be [0, _D_HUE_MAX]
s = ((float)s)/_D_saturation_MAX; // s must be [0, 1]
l = ((float)l)/_D_luminance_MAX; // l must be [0, 1]
if(hsl.s == 0)
{
// achromatic color (gray scale)
color.r=color.g=color.b= l*255.f;
}
else
{
float q = (l<0.5f)?(l * (1.0f+s)):(l+s - (l*s));
float p = (2.0f * l) - q;
float hk = h/_D_HUE_MAX;
float *tc=(float *) &color;
color.r = hk + 1.0/3.0; // Tr 0.3333333f=1.0/3.0
color.g = hk; // Tb
color.b = hk - 1.0/3.0; // Tg
for(int i=0; i<3; i++)
{
if(tc[i] < 0) tc[i] += 1.0f;
if(tc[i] > 1) tc[i] -= 1.0f;
if((tc[i]*6) < 1)
{
tc[i] = p + ((q-p)*6.0f*tc[i]);
}
else if(1.0<=(tc[i]*6.0) && tc[i]<0.5 )
{
tc[i] = q;
}
else if( 0.5<=tc[i] && (tc[i]*3.0)<2.0 )
{
tc[i] = p + (q-p) * ((2.0f/3.0f) - tc[i]) * 6.0f;
}
else tc[i] = p;
}
color.r*=255.0f;
color.g*=255.0f;
color.b*=255.0f;
}
if( 0!=rgb )
{
rgb->r = (uint8_t)((color.r>255)? 255 : ((color.r<0)?0 : color.r));
rgb->g = (uint8_t)((color.g>255)? 255 : ((color.g<0)?0 : color.g));
rgb->b = (uint8_t)((color.b>255)? 255 : ((color.b<0)?0 : color.b));
return *rgb;
}
else
{
rgba.r = (uint8_t)((color.r>255)? 255 : ((color.r<0)?0 : color.r));
rgba.g = (uint8_t)((color.g>255)? 255 : ((color.g<0)?0 : color.g));
rgba.b = (uint8_t)((color.b>255)? 255 : ((color.b<0)?0 : color.b));
return rgba;
}
}
HSL 与 RGB 互换
于 2022-05-09 00:14:25 首次发布