binary_clock/include/colors.h

152 lines
3.0 KiB
C
Executable File

typedef struct {
double r; // a fraction between 0 and 1
double g; // a fraction between 0 and 1
double b; // a fraction between 0 and 1
} rgb;
typedef struct {
double h; // angle in degrees
double s; // a fraction between 0 and 1
double v; // a fraction between 0 and 1
} hsv;
static rgb int2rgb(uint32_t in);
static hsv rgb2hsv(rgb in);
static rgb hsv2rgb(hsv in);
rgb int2rgb(uint32_t in)
{
rgb out;
out.r = (in >> 16) & 255;
out.g = (in >> 8) & 255;
out.b = in & 255;
return out;
}
hsv rgb2hsv(rgb in)
{
hsv out;
double min, max, delta;
min = in.r < in.g ? in.r : in.g;
min = min < in.b ? min : in.b;
max = in.r > in.g ? in.r : in.g;
max = max > in.b ? max : in.b;
out.v = max;
delta = max - min;
if (delta < 0.00001)
{
out.s = 0;
out.h = 0;
return out;
}
if(max > 0.0)
{
out.s = (delta / max);
}
else
{
out.s = 0.0;
out.h = 0;
return out;
}
if(in.r >= max)
out.h = ( in.g - in.b ) / delta;
else if(in.g >= max)
out.h = 2.0 + ( in.b - in.r ) / delta;
else
out.h = 4.0 + ( in.r - in.g ) / delta;
out.h *= 60.0;
if(out.h < 0.0)
out.h += 360.0;
return out;
}
rgb hsv2rgb(hsv in)
{
double hh, p, q, t, ff;
long i;
rgb out;
if(in.s <= 0.0)
{
out.r = in.v;
out.g = in.v;
out.b = in.v;
return out;
}
hh = in.h;
if(hh >= 360.0)
hh = 0.0;
hh /= 60.0;
i = (long)hh;
ff = hh - i;
p = in.v * (1.0 - in.s);
q = in.v * (1.0 - (in.s * ff));
t = in.v * (1.0 - (in.s * (1.0 - ff)));
switch(i)
{
case 0:
out.r = in.v;
out.g = t;
out.b = p;
break;
case 1:
out.r = q;
out.g = in.v;
out.b = p;
break;
case 2:
out.r = p;
out.g = in.v;
out.b = t;
break;
case 3:
out.r = p;
out.g = q;
out.b = in.v;
break;
case 4:
out.r = t;
out.g = p;
out.b = in.v;
break;
case 5:
default:
out.r = in.v;
out.g = p;
out.b = q;
break;
}
return out;
}
rgb gradient(rgb start, rgb end, double ratio)
{
if(ratio < 0)
ratio = 0;
if(ratio > 1)
ratio = 1;
auto start_hsv = rgb2hsv(start);
auto end_hsv = rgb2hsv(end);
hsv result;
result.h = start_hsv.h + ratio * (end_hsv.h - start_hsv.h);
result.s = start_hsv.s + ratio * (end_hsv.s - start_hsv.s);
result.v = start_hsv.v + ratio * (end_hsv.v - start_hsv.v);
return hsv2rgb(result);
}