To convert colors from the RGB (red-green-blue) to the HCL (hue-chroma-lightness) system in R (or any other software), we need to go through XYZ and CIE-LAB color systems.
What is a RGB color?
A RGB color is composed of three to four values ranging from 0 to 255:
- one value for the red
- one value for the green
- one value for the blue
- one value for the transparency (facultative)
For example, let’s take the following values for red, green and blue, respectively:
RGB = c(237, 180, 232)
barplot(1, col = rgb(RGB[1]/255, RGB[2]/255, RGB[3]/255), axes = F)
What is a HCL color?
A HCL (or LCH) color is composed of three values:
- one value for the hue (ranging from 0 to 360°)
- one value for the chroma (ranging from 0 to 100%)
- one value for the light / luminance / lightness / luminosity (ranging from 0 to 100%)
However, it is important to note that the hue is slightly different from the ones of HSL, HSV and HSI.
From RGB to HCL colors in R
To make the conversion between RGB and HCL color systems (and vice versa), we need to go through XYZ and CIE-LAB color systems. In the next sections, we will implement the formulas from the EasyRGB website.
from_rgb_to_hcl = function(RGB, color_model){
R = RGB[1] / 255
G = RGB[2] / 255
B = RGB[3] / 255
if (R > 0.04045){
R = ((R + 0.055) / 1.055) ^ 2.4
} else {
R = R / 12.92
}
if (G > 0.04045){
G = ((G + 0.055) / 1.055) ^ 2.4
} else {
G = G / 12.92
}
if (B > 0.04045){
B = ((B + 0.055) / 1.055) ^ 2.4
} else {
B = B / 12.92
}
R = R * 100
G = G * 100
B = B * 100
X = R * 0.4124 + G * 0.3576 + B * 0.1805
Y = R * 0.2126 + G * 0.7152 + B * 0.0722
Z = R * 0.0193 + G * 0.1192 + B * 0.9505
XYZ = matrix(c(X, Y, Z))
rownames(XYZ) = c("X", "Y", "Z")
X = X / 95.047
Y = Y / 100
Z = Z / 108.883
if (X > 0.008856){
X = X ^ (1 / 3)
} else {
X = (7.787 * X) + (16 / 116)
}
if (Y > 0.008856){
Y = Y ^ (1 / 3)
} else {
Y = (7.787 * Y) + (16 / 116)
}
if (Z > 0.008856){
Z = Z ^ (1 / 3)
} else {
Z = (7.787 * Z) + (16 / 116)
}
L = (116 * Y) - 16
A = 500 * (X - Y)
B = 200 * (Y - Z)
LAB = matrix(c(L, A, B))
rownames(LAB) = c("L", "A", "B")
H = atan2(B, A)
if (H > 0){
H = (H / pi) * 180
} else {
H = 360 - (abs(H) / pi) * 180
}
C = sqrt(A ^ 2 + B ^ 2)
HCL = matrix(c(H, C, L))
rownames(HCL) = c("H", "C", "L")
if (color_model == "XYZ"){
return(XYZ)
} else if (color_model == "LAB"){
return(LAB)
} else if (color_model == "HCL"){
return(HCL)
}
}
HCL = from_rgb_to_hcl(RGB, "HCL")
> from_rgb_to_hcl(RGB, "XYZ")
[,1]
X 65.81180
Y 56.47324
Z 83.77570
> from_rgb_to_hcl(RGB, "LAB")
[,1]
L 79.88240
A 29.05609
B -17.95184
> from_rgb_to_hcl(RGB, "HCL")
[,1]
H 328.29082
C 34.15443
L 79.88240
From HCL to RGB colors in R
from_hcl_to_rgb = function(HCL, color_model){
H = HCL[1]
C = HCL[2]
L = HCL[3]
A = cos((H * pi) / 180) * C
B = sin((H * pi) / 180) * C
LAB = matrix(c(L, A, B))
rownames(LAB) = c("L", "A", "B")
Y = (L + 16) / 116
X = A / 500 + Y
Z = Y - B / 200
if (Y^3 > 0.008856){
Y = Y^3
} else {
Y = (Y - 16 / 116) / 7.787
}
if (X^3 > 0.008856){
X = X^3
} else {
X = (X - 16 / 116) / 7.787
}
if (Z^3 > 0.008856){
Z = Z^3
} else {
Z = (Z - 16 / 116) / 7.787
}
X = X * 95.047
Y = Y * 100
Z = Z * 108.883
XYZ = matrix(c(X, Y, Z))
rownames(XYZ) = c("X", "Y", "Z")
X = X / 100
Y = Y / 100
Z = Z / 100
R = X * 3.2406 + Y * -1.5372 + Z * -0.4986
G = X * -0.9689 + Y * 1.8758 + Z * 0.0415
B = X * 0.0557 + Y * -0.2040 + Z * 1.0570
if (R > 0.0031308){
R = 1.055 * (R ^ (1 / 2.4)) - 0.055
} else {
R = 12.92 * R
}
if (G > 0.0031308){
G = 1.055 * (G ^ (1 / 2.4)) - 0.055
} else {
G = 12.92 * G
}
if (B > 0.0031308){
B = 1.055 * (B ^ (1 / 2.4)) - 0.055
} else {
B = 12.92 * B
}
RGB = matrix(c(R, G, B) * 255)
mode(RGB) = "integer"
rownames(RGB) = c("red", "green", "blue")
if (color_model == "LAB"){
return(LAB)
} else if (color_model == "XYZ"){
return(XYZ)
} else if (color_model == "RGB"){
return(RGB)
}
}
> from_hcl_to_rgb(HCL, "LAB")
[,1]
L 79.88240
A 29.05609
B -17.95184
> from_hcl_to_rgb(HCL, "XYZ")
[,1]
X 65.81180
Y 56.47324
Z 83.77570
> from_hcl_to_rgb(HCL, "RGB")
[,1]
red 237
green 180
blue 232
Conclusion
It was again a good exercise to implement the conversion between RGB and HCL color spaces in R. Is this article useful to you?