From RGB to HSL colors in R (and vice versa)

In this tutorial, we will see how to convert colors from the RGB (red-green-blue) to the HSL (hue-saturation-lightness), HSV (hue-saturation-value) or HSI (hue-saturation-intensity) systems in R (and vice versa).

If you are interested, I have already written a blog post about how to convert colors between RGB and HEX in R.

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(127.5, 127.5, 255)
barplot(1, col = rgb(RGB[1]/255, RGB[2]/255, RGB[3]/255), axes = F)

What is a HSL, HSV or HSI color?

Before digging into this subject, I invite you to browse this very complete page about HSL, HSV and HSI from Wikipedia. After that, we will use the fact that the three color systems are composed of three values. The two first ones are:

  • the hue (ranging from 0 to 360°) which is identical in the three cases
  • the saturation (ranging from 0 to 100 %) which is different in the three cases

Then, the third one is:

  • the light / luminance / lightness / luminosity (ranging from 0 to 100 %) for HSL
  • the value / brightness (ranging from 0 to 100 %) for HSV
  • the intensity (ranging from 0 to 100 %) for HSI

Consequently, we will implement the HSL, HSV and HSI formulas from Wikipedia in R.

From RGB to HSL, HSV or HSI colors in R

from_rgb_to_hsl = function(RGB, color_model){
  R = RGB[1] / 255
  G = RGB[2] / 255
  B = RGB[3] / 255
  
  M = max(c(R, G, B))
  m = min(c(R, G, B))
  C = M - m
  
  if (C == 0){
    H = 0
    
  } else {
    if (M == R){
      H = ((G - B) / C) %% 6
      
    } else if (M == G){
      H = ((B - R) / C) + 2
      
    } else if (M == B){
      H = ((R - G) / C) + 4
    }
  }
  
  if (color_model == "HSI"){
    I = (R + G + B) / 3
    S = ifelse(I == 0, 0, 1 - (m / I))
    params = c(H * 60, S * 100, I * 100)
    
  } else if (color_model == "HSV" | color_model == "HSB"){
    V = M
    S = ifelse(V == 0, 0, C / V)
    params = c(H * 60, S * 100, V * 100)
    
  } else if (color_model == "HSL"){
    L = (M + m) / 2
    S = ifelse(L == 0 | L == 1, 0, C / (1 - abs(2 * L - 1)))
    params = c(H * 60, S * 100, L * 100)
  }
  
  params = matrix(params)
  rownames(params) = unlist(strsplit(color_model, ""))
  
  return(params)
}

HSI = from_rgb_to_hsl(RGB, "HSI")
HSV = from_rgb_to_hsl(RGB, "HSV")
HSL = from_rgb_to_hsl(RGB, "HSL")
> from_rgb_to_hsl(RGB, "HSI")
       [,1]
H 240.00000
S  25.00000
I  66.66667

> from_rgb_to_hsl(RGB, "HSV")
  [,1]
H  240
S   50
V  100

> from_rgb_to_hsl(RGB, "HSL")
  [,1]
H  240
S  100
L   75

From HSL, HSV or HSI to RGB colors in R

from_hsl_to_rgb = function(params, color_model){
  H = params[1] / 60
  S = params[2] / 100
  
  if (color_model == "HSI"){
    I = params[3] / 100
    Z = 1 - abs(H %% 2 - 1)
    C = (3 * I * S) / (1 + Z)
    X = C * Z
    
  } else if (color_model == "HSV"){
    V = params[3] / 100
    C = V * S
    X = C * (1 - abs(H %% 2 - 1))
    
  } else if (color_model == "HSL"){
    L = params[3] / 100
    C = (1 - abs(2 * L -1)) * S
    X = C * (1 - abs(H %% 2 - 1))
  }
  
  if (H >= 0 & H < 1){
    R = C
    G = X
    B = 0
    
  } else if (H >= 1 & H < 2){
    R = X
    G = C
    B = 0
    
  } else if (H >= 2 & H < 3){
    R = 0
    G = C
    B = X
    
  } else if (H >= 3 & H < 4){
    R = 0
    G = X
    B = C
    
  } else if (H >= 4 & H < 5){
    R = X
    G = 0
    B = C
    
  } else if (H >= 5 & H < 6){
    R = C
    G = 0
    B = X
  }
  
  if (color_model == "HSI"){
    m = I * (1 - S)
    
  } else if (color_model == "HSV"){
    m = V - C
    
  } else if (color_model == "HSL"){
    m = L - C / 2
  }
  
  RGB = matrix((c(R, G, B) + m) * 255)
  rownames(RGB) = c("red", "green", "blue")
  
  return(RGB)
}
> from_hsl_to_rgb(HSI, "HSI")
       [,1]
red   127.5
green 127.5
blue  255.0

> from_hsl_to_rgb(HSV, "HSV")
       [,1]
red   127.5
green 127.5
blue  255.0

> from_hsl_to_rgb(HSL, "HSL")
       [,1]
red   127.5
green 127.5
blue  255.0

Conclusion

In conclusion, it was a good exercise to implement the HSL, HSV and HSI formulas in R. How would you improve this function?

Related posts

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply