I'm trying to get a HSL color value from my Database. Currently there is only a RGB value stored. Let's assume I got separate columns for rgb: red green blue with a number value 0-255 in them each.
Target result would be hue saturation lightness in the resultset, calculated from the rgb values. I've seen a lot of calculations but none of them seem easy enough to do in a query? Or I'm not deeply enough into SQL in general to know how to port something like a switch statement to SQL.
The best example for converting I've found is here: How do you get the hue of a #xxxxxx colour?
function rgbToHsl(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
}
But I'm completely stumped for an answer on how to do something like this calculation in SQL.
After it not working quite correctly (the code sample above is incorrect from what I can see on wikipedia for conversion of the hue, as well as I needed the hue in full degrees 0-360 rather than between 0 and 1) I've started with the solution from Arth and got to this, I've decided to to a /255 on r,g,b beforehand because that is just easier to follow through from the above code sample:
CASE
WHEN r>=g AND g>=b THEN ((g-b)/(r-b))*60
WHEN g>r AND r>=b THEN (2-(r-b)/(g-b))*60
WHEN g>=b AND b>r THEN (2+(b-r)/(g-r))*60
WHEN b>g AND g>r THEN (4-(g-r)/(b-r))*60
WHEN b>r AND r>=g THEN (4+(r-g)/(b-g))*60
WHEN r>=b AND b>g THEN (6-(b-g)/(r-g))*60
END h,
CASE
WHEN r=g AND g=b THEN 0
WHEN r>=g AND g>=b AND (r-b)>0.5 THEN (r-b)/(2-r-b)
WHEN r>=g AND g>=b THEN (r-b)/(r+b)
WHEN r>=g AND b>g AND (r-g)>0.5 THEN (r-g)/(2-r-g)
WHEN r>=g AND b>g THEN (r-g)/(r+g)
WHEN g>=r AND r>=b AND (g-b)>0.5 THEN (g-b)/(2-g-b)
WHEN g>=r AND r>=b THEN (g-b)/(g+b)
WHEN g>=r AND b>r AND (g-r)>0.5 THEN (g-r)/(2-g-r)
WHEN g>=r AND b>r THEN (g-r)/(g+r)
WHEN b>=r AND r>=g AND (b-g)>0.5 THEN (b-g)/(2-b-g)
WHEN b>=r AND r>=g THEN (b-g)/(b+g)
WHEN b>=r AND g>r AND (b-r)>0.5 THEN (b-r)/(2-b-r)
WHEN b>=r AND g>r THEN (b-r)/(b+r)
END s,
CASE
WHEN r=g AND g=b THEN r
WHEN r>=g AND g>=b THEN (r+b)/2
WHEN r>=g AND b>g THEN (r+g)/2
WHEN g>=r AND r>=b THEN (g+r)/2
WHEN g>=r AND b>r THEN (g+b)/2
WHEN b>=r AND r>=g THEN (b+g)/2
WHEN b>=r AND g>r THEN (b+r)/2
END l
It is an absolute nightmare and not tested, but I've had a go:
SELECT
CASE
WHEN r=g AND g=b THEN 0
WHEN r>=g AND g>b THEN ((g-b)/(r-b))/6
WHEN r>=g AND b>=g THEN ((g-b)/(r-g)+6)/6
WHEN g>=r AND r>=b THEN ((b-r)/(g-b)+2)/6
WHEN g>=r AND b>r THEN ((b-r)/(g-r)+2)/6
WHEN b>=r AND r>=g THEN ((r-g)/(b-g)+4)/6
WHEN b>=r AND g>r THEN ((r-g)/(b-r)+4)/6
END h,
CASE
WHEN r=g AND g=b THEN 0
WHEN r>=g AND g>=b AND (r-b)>0.5*255 THEN (r-b)/(510-r-b)
WHEN r>=g AND g>=b THEN (r-b)/(r+b)
WHEN r>=g AND b>g AND (r-g)>0.5*255 THEN (r-g)/(510-r-g)
WHEN r>=g AND b>g THEN (r-g)/(r+g)
WHEN g>=r AND r>=b AND (g-b)>0.5*255 THEN (g-b)/(510-g-b)
WHEN g>=r AND r>=b THEN (g-b)/(g+b)
WHEN g>=r AND b>r AND (g-r)>0.5*255 THEN (g-r)/(510-g-r)
WHEN g>=r AND b>r THEN (g-r)/(g+r)
WHEN b>=r AND r>=g AND (b-g)>0.5*255 THEN (b-g)/(510-b-g)
WHEN b>=r AND r>=g THEN (b-g)/(b+g)
WHEN b>=r AND g>r AND (b-r)>0.5*255 THEN (b-r)/(510-b-r)
WHEN b>=r AND g>r THEN (b-r)/(b+r)
END s,
CASE
WHEN r=g AND g=b THEN r/255
WHEN r>=g AND g>=b THEN (r+b)/510
WHEN r>=g AND b>g THEN (r+g)/510
WHEN g>=r AND r>=b THEN (g+r)/510
WHEN g>=r AND b>r THEN (g+b)/510
WHEN b>=r AND r>=g THEN (b+g)/510
WHEN b>=r AND g>r THEN (b+r)/510
END l
FROM table1
In conclusion, you are probably better off selecting the RGB values and running the conversion at the application level!