Post

RGB를 HSL로 바꿔보자

RGB 색 표현 방식은 우리의 눈이 색을 인지하는 방식을 모델링합니다.

우리의 시각세포 중 원추세포는 r, g, b의 세기를 감지하여 다양한 색깔을 볼 수 있습니다. 이 방식 그대로 (r, g, b) 의 방식으로 나타낸 것이 RGB 색 표현 방식입니다

각각의 값은 0부터 255 중 하나이며 가장 작은 값은 0, 가장 큰 값은 255가 됩니다.

이를 통해 우리는 자연스럽게 모든 색을 RGB 색 표현 방식으로 나타낼 수 있게 됩니다. RGB 색 표현 방식에서, R축, G축, B축을 cubic 좌표 공간에 나타내면 아래와 같은 모습이 나타나게 됩니다.

이런 방식은 개발자에게 가장 익숙한 방법이기도 합니다.

한편, HSL 방식은 다양한 페인트가 혼합되어 현실 세계의 색을 생성하는 방식을 모델링합니다. Hue는 빛깔(어떤 색의 페인트를 쓰는가), Lightness는 밝기(흰색 페인트를 얼마나 썼는가), Saturation는 채도(얼마나 선명하게 색깔이 나타나는가)를 나타냅니다.

이 방식은 우리가 비슷하다고 느끼는 색을 구별하는 방식과 유사합니다. 우리는 비슷한 밝기, 비슷한 채도, 비슷한 빛깔을 가진 색끼리 그룹짓는 경향이 강하기 때문입니다.

그렇다면 RGB 공간을 어떻게 HSL 방식으로 전사할 수 있을까요?

먼저, 위 그림의 RGB 큐브의 6개의 꼭짓점 중 어디로 향하는지에 따라 Hue 값을 정하는게 자연스러워보입니다. 이를 위해서 위의 정육면체를 (0,0,0)기준으로 세워서 cylindrical 좌표공간에 넣어봅시다.

위 그림과 같이 Hue에 해당하는 정육각형이 나오게 되었습니다.

위 정육면체에서 Hue를 정의하면,

빨간색 방향을 0이라고 했을 때, 벡터의 각도

가 될 수 있겠습니다. 빨간색이 0이므로, 초록색은 120도, 파란색은 240도가 되겠네요.

이렇게 Hue 성분이 정의되었습니다.

Hue는 r, g, b 벡터에서 다음과 같은 방식으로 구할 수 있습니다.


RGB to HSL conversion

증명은 여기 참조.

Lightness는 상당히 직관적입니다. 정육면체를 세웠을 때, 바닥 평면과의 거리가 직관적으로 Lightness로 정의될 수 있음을 확인할 수 있습니다. white가 가장 높이가 높고, black이 가장 낮기 때문입니다.

마지막으로, Saturation입니다.

채도는 각 r, g, b 벡터의 크기가 커서 중심축으로부터의 거리가 멀어질수록 강하게 나타납니다.

따라서 우리는 chroma를 각 벡터 크기의 최댓값과 최솟값의 차이로 정의합니다.

  • 최댓값과 최솟값 차이가 작다. → 세 벡터를 합치면 그 어느 hue로도 향하지 않는다. → 채도가 낮다.
  • 최댓값과 최솟값 차이가 크다. → 세 벡터 중 최댓값을 나타내는 hue로 향하게 된다. → 채도가 높다.

이를 hue와 lightness의 차원에 맞게 [0, 1] 구간에 나타나도록 조절해주면 됩니다.

위 과정을 통해 우리는 R-G-B와 H-S-L의 표현방식에 대해 더 잘 이해할 수 있습니다.

참고자료


https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c

This post is licensed under CC BY 4.0 by the author.