미완
0. 목적
이 글은 무식하게 RGB 255 255 255 중얼거리기에서 탈출하기 위함이다.
컴퓨터 그래픽의 원천은 인간의 눈이다.
예를 들어 빛을 표현하는 방법은 RGB 외에도 많을텐데 굳이 이 방법을 취한 까닭은 우리 눈의 원추세포가 거의 이 구조와 흡사하기 때문이다.
여기서 우리는 자주 쓰이는 2가지 변환을 이해할 것이다.
GrayScale, Gamma Correction
출처는 다 위키이다. 다 위키에서 긁었다.
1. GrayScale
이건 이해하기가 매우 쉽다. 정확히는 아.. 그런 갑다. 하고 넘어가기가 매우 쉽다.
Luminosity function 이 뭐냐면 x 축은 주파수고 y 축은 민감도를 나타내서 우리 눈이 어떤 색에 민감한지 알려주는 그래프다.
주파수와 색깔을 매치시키면 초록색에 민감한 걸 알 수 있다.
그래서 나오는게 여러가지 버전 GrayScale 인데, 잘 쓰이는건 아래와 같다.
linear 은 뒤에 설명할테니 계수에 집중하자.
초록색이 넘사벽이고 빨강, 파랑 순으로 우리 눈이 민감하다. 그래서 사람의 눈은 초록색이 적으면 상대적으로 어둡게 생각한다.
이를 반영해서 컬러 사진을 흑백 사진으로 바꾸면 효과적으로 표현이 가능하고, 그래픽 효과를 줄 때 픽셀의 밝기도 GrayScale 로 걸러서 사용한다.
2. Gamma Correction
사람의 눈은 색상에 따라 민감도가 다르지만, 밝기에 따라 민감도가 또 다르다.
밝은 정도는 차이를 구분 잘 못하는데, 어두운 정도의 차이는 쉽게 구분할 수 있다. (이런 관계를 비선형 - nonLinear 이라고 부른다.)
그러므로 픽셀을 표현할 때 밝은 정도와 어두운 정도에 관계 없이 절대적인 빛의 크기에 따라 값을 할당하면 낭비가 발생한다.
예를 들어보자.
A는 8bit 정수가 있어서 0~200 은 어두운 부분을 표현하고, 201_255 는 밝은 부분을 표현한다.
B는 8bit 정수가 있어서 0~255 모두 절대적인 빛의 크기에 따라 균등하게 표현한다.
사람에게 인식되어 표현 가능한 밝기 등의 범위가 B보다 A가 더 클 것이다. 그래서 A 같은 짓을 하는 것이 Gamma Correction 이다.
위 식을 가지고 앞으로 놀 것이다.
이 변환은 float 과 int 사이에서 일어난다. float 은 0~1 에선 매우 정밀하게 표현 가능하기 때문에 선형적으로 표현할 것이고 int 는 비선형적으로 표현할 것이다. float 의 특성은 곧 0~1 사이로 정규화하는 이유 중 하나다.
A는 상수니까 무시하고, input, output, gamma 가 어떻게 쓰이는지 확인하자.
input 은 0~1로 정규화한 float 을 사용한다.
r 는 float -> int 로 encoding 시 0~1 사이로, int -> float 로 디코딩 시 1 이상의 값을 사용한다.
encoding이 어떻게 일어나는지 살펴보기위해 무식한 노가다를 해보겠다.
gamma 가 0.5 일 때 input 의 값에 따른 분포는 다음과 같다.
0.1 = 0.316227766017
0.2 = 0.4472135955
0.3 = 0.547722557505
0.4 = 0.632455532034
0.5 = 0.707106781187
0.6 = 0.774596669241
0.7 = 0.836660026534
0.8 = 0.894427191
0.9 = 0.948683298051
input 이 작으면, 즉 어두울 때 표현되는 간격은 넓어지고, input 이 크면, 즉 밝을 때 표현되는 간격은 좁아진다. 즉 어두운 것을 더 세밀하게 표현하겠다는 말이다. 위 값에서 8bit 정수면 255 값을 곱해서 정수로 만들면 된다.
근데 float 가 표현이 쉬우면 그거만 쓰면 되지 왜 int 를 쓰냐. 그 이유는 부동소수점보단 정수가 관리가 쉽기 때문이다. 덧붙여 jpj 형식같이 이미지파일은 gamma 값을 따로 저장하는 경우가 많다.
3. sRGB
display divice 는 0~1 사이의 값으로 빛의 세기를 조절한다. 값이 정규화되었기 때문에, 장치가 절대적으로 표현할 수 있는 빛의 크기의 범위는 이것 만으론 알 수 없다.
그래서 장치마다 decoding 용 gamma 값이 정해져 있다.
gamma 값을 포함한 기본적인 RGB 색상 공간 중 가장 널리 쓰이는 것이 바로 sRGB 이다.
여기서 색상공간이라는게 그 벡터 공간 이야기하는게 맞다. CIE 색상 공간이 더 넓게 쓰이는 색상 공간이고 그 공간에서 축을 바꿔서 변형한 것 중 하나가 sRGB 이다.
R8G8B8A8 형식의 이미지 파일은 대게 sRGB 이다. 그래서 float 형식의 텍스쳐 파일과 int 형식의 텍스쳐 파일을 연동시키려면 gamma 변환을 해야한다.
댓글 없음:
댓글 쓰기