103 lines
2.4 KiB
C++
103 lines
2.4 KiB
C++
|
#include "color.h"
|
||
|
|
||
|
// taken from
|
||
|
// https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
|
||
|
hsv_t rgb2hsv(color_t in) {
|
||
|
hsv_t out;
|
||
|
double min, max, delta;
|
||
|
|
||
|
min = in.red < in.green ? in.red : in.green;
|
||
|
min = min < in.blue ? min : in.blue;
|
||
|
|
||
|
max = in.red > in.green ? in.red : in.green;
|
||
|
max = max > in.blue ? max : in.blue;
|
||
|
|
||
|
out.val = max; // v
|
||
|
delta = max - min;
|
||
|
if (delta < 0.00001) {
|
||
|
out.sat = 0;
|
||
|
out.hue = 0; // undefined, maybe nan?
|
||
|
return out;
|
||
|
}
|
||
|
if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash
|
||
|
out.sat = (delta / max); // s
|
||
|
} else {
|
||
|
// if max is 0, then r = g = b = 0
|
||
|
// s = 0, h is undefined
|
||
|
out.sat = 0.0;
|
||
|
out.hue = NAN; // its now undefined
|
||
|
return out;
|
||
|
}
|
||
|
if (in.red >= max) // > is bogus, just keeps compilor happy
|
||
|
out.hue = (in.green - in.blue) / delta; // between yellow & magenta
|
||
|
else if (in.green >= max)
|
||
|
out.hue = 2.0 + (in.blue - in.red) / delta; // between cyan & yellow
|
||
|
else
|
||
|
out.hue = 4.0 + (in.red - in.green) / delta; // between magenta & cyan
|
||
|
|
||
|
out.hue *= 60.0; // degrees
|
||
|
|
||
|
if (out.hue < 0.0)
|
||
|
out.hue += 360.0;
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
color_t hsv2rgb(hsv_t in) {
|
||
|
double hh, p, q, t, ff;
|
||
|
long i;
|
||
|
color_t out;
|
||
|
|
||
|
if (in.sat <= 0.0) { // < is bogus, just shuts up warnings
|
||
|
out.red = in.val;
|
||
|
out.green = in.val;
|
||
|
out.blue = in.val;
|
||
|
return out;
|
||
|
}
|
||
|
hh = in.hue;
|
||
|
if (hh >= 360.0)
|
||
|
hh = 0.0;
|
||
|
hh /= 60.0;
|
||
|
i = (long) hh;
|
||
|
ff = hh - i;
|
||
|
p = in.val * (1.0 - in.sat);
|
||
|
q = in.val * (1.0 - (in.sat * ff));
|
||
|
t = in.val * (1.0 - (in.sat * (1.0 - ff)));
|
||
|
|
||
|
switch (i) {
|
||
|
case 0:
|
||
|
out.red = in.val;
|
||
|
out.green = t;
|
||
|
out.blue = p;
|
||
|
break;
|
||
|
case 1:
|
||
|
out.red = q;
|
||
|
out.green = in.val;
|
||
|
out.blue = p;
|
||
|
break;
|
||
|
case 2:
|
||
|
out.red = p;
|
||
|
out.green = in.val;
|
||
|
out.blue = t;
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
out.red = p;
|
||
|
out.green = q;
|
||
|
out.blue = in.val;
|
||
|
break;
|
||
|
case 4:
|
||
|
out.red = t;
|
||
|
out.green = p;
|
||
|
out.blue = in.val;
|
||
|
break;
|
||
|
case 5:
|
||
|
default:
|
||
|
out.red = in.val;
|
||
|
out.green = p;
|
||
|
out.blue = q;
|
||
|
break;
|
||
|
}
|
||
|
return out;
|
||
|
}
|