xref: /haiku/src/kits/shared/HSL.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
1 /*
2  * Copyright 2024, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <HSL.h>
8 
9 
10 hsl_color
11 hsl_color::from_rgb(const rgb_color& rgb)
12 {
13 	hsl_color result;
14 
15 	float r = rgb.red / 255.0f;
16 	float g = rgb.green / 255.0f;
17 	float b = rgb.blue / 255.0f;
18 
19 	float max = max_c(max_c(r, g), b);
20 	float min = min_c(min_c(r, g), b);
21 
22 	result.hue = result.saturation = result.lightness = (max + min) / 2;
23 
24 	if (max == min) {
25 		// grayscale
26 		result.hue = result.saturation = 0;
27 	} else {
28 		float diff = max - min;
29 		result.saturation
30 			= (result.lightness > 0.5) ? (diff / (2 - max - min)) : (diff / (max + min));
31 
32 		if (max == r)
33 			result.hue = (g - b) / diff + (g < b ? 6 : 0);
34 		else if (max == g)
35 			result.hue = (b - r) / diff + 2;
36 		else if (max == b)
37 			result.hue = (r - g) / diff + 4;
38 
39 		result.hue /= 6;
40 	}
41 
42 	return result;
43 }
44 
45 
46 rgb_color
47 hsl_color::to_rgb() const
48 {
49 	rgb_color result;
50 	result.alpha = 255;
51 
52 	if (saturation == 0) {
53 		// grayscale
54 		result.red = result.green = result.blue = uint8(lightness * 255);
55 	} else {
56 		float q = lightness < 0.5 ? (lightness * (1 + saturation))
57 			: (lightness + saturation - lightness * saturation);
58 		float p = 2 * lightness - q;
59 		result.red = uint8(hue_to_rgb(p, q, hue + 1./3) * 255);
60 		result.green = uint8(hue_to_rgb(p, q, hue) * 255);
61 		result.blue = uint8(hue_to_rgb(p, q, hue - 1./3) * 255);
62 	}
63 
64 	return result;
65 }
66 
67 
68 // reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Color_conversion_formulae
69 // (from_rgb() and to_rgb() are derived from the same)
70 float
71 hsl_color::hue_to_rgb(float p, float q, float t)
72 {
73 	if (t < 0)
74 		t += 1;
75 	if (t > 1)
76 		t -= 1;
77 	if (t < 1./6)
78 		return p + (q - p) * 6 * t;
79 	if (t < 1./2)
80 		return q;
81 	if (t < 2./3)
82 		return p + (q - p) * (2./3 - t) * 6;
83 
84 	return p;
85 }
86