감마 보정
화면에 내보낼 색 값을 미리 비틀어 적어 두고, 화면 쪽이 그것을 되비틀어 원래대로 돌려놓는 일입니다. 표시 장치가 받은 값을 그대로 밝기로 바꾸지 않기 때문에 생긴 짝입니다. 적는 쪽과 보여 주는 쪽이 서로 반대 방향으로 한 번씩 걸어야 처음 밝기가 나옵니다.
상세
눈금 간격이 고르지 않은 자를 떠올려 봅니다. 앞쪽은 촘촘하고 뒤쪽은 성깁니다. 적는 쪽에서 그 치우침만큼 미리 반대로 비틀어 적어 두면, 이 자로 읽어도 제 길이가 나옵니다.
감마 보정은 두 가지 일을 한 이름으로 부르는 말입니다. 하나는 신호를 만드는 쪽이 밝기 값을 비선형으로 부호화하는 것입니다. 다른 하나는 보여 주는 쪽이 그 부호를 다시 밝기로 되돌리는 것입니다. 두 함수는 서로 역함수 관계입니다. 이어 붙이면 처음 넣은 밝기가 그대로 나옵니다.
빛을 신호로 바꾸는 쪽에 거는 함수를 OETF(Opto-Electronic Transfer Function, 광전 전달 함수), 신호를 빛으로 바꾸는 쪽에 거는 함수를 EOTF(Electro-Optical Transfer Function, 전광 전달 함수)라고 부릅니다.
flowchart TD
L1["선형 빛 값"] -->|부호화| E["부호화된 값"]
E --> S["저장 · 전송"]
S -->|복호화| L2["선형 빛 값"]
L2 --> D["화면 밝기"]
왼쪽 끝과 오른쪽 끝만 같으면 됩니다. 가운데 구간에 실려 다니는 숫자는 밝기가 아닙니다. 밝기를 비틀어 적어 둔 부호입니다.
이 구분이 감마 보정의 핵심입니다. 부호는 더하거나 평균 내는 계산에 그대로 쓸 수 없습니다. 비선형으로 비튼 값 두 개를 반씩 섞은 결과는, 두 밝기를 반씩 섞은 값과 다릅니다. 섞는 계산은 되돌린 뒤에 해야 맞습니다.
배경
음극선관(CRT, Cathode-Ray Tube) 표시 장치는 들어온 전압에 비례해서 밝아지지 않았습니다. 전압을 두 배로 올려도 화면이 두 배로 밝아지지 않습니다. 밝기는 전압을 거듭제곱한 꼴로 따라옵니다. 밝기 값을 그대로 실어 보내면 화면에 나온 그림은 원래보다 어둡게 눌립니다.
필요한 것은 그 눌림을 미리 상쇄해 둘 자리였습니다. 화면 쪽을 하나하나 고치는 길도 있었지만, 화면은 수없이 많고 신호를 만드는 쪽은 몇 곳뿐입니다. 그래서 상쇄는 신호를 만드는 쪽에서 한 번 걸어 두는 쪽으로 굳었습니다. 덤으로 딸려 온 것이 하나 더 있습니다. 사람 눈은 어두운 쪽의 밝기 차이를 밝은 쪽보다 잘 가려냅니다. 비틀어 적은 값은 같은 비트 수를 어두운 쪽에 더 촘촘히 나눠 주기 때문에, 어두운 면에 생기는 계단 자국이 덜 눈에 띕니다.
이름은 그 거듭제곱의 지수에서 왔습니다. 지수를 그리스 문자 감마로 적어 왔고, 그 지수를 반대 방향으로 상쇄하는 일을 감마 보정이라고 부릅니다. 지금의 평판 표시 장치는 그런 응답을 물리적으로 갖지 않습니다. 그래도 같은 곡선을 되돌리도록 맞춥니다. 이미 만들어진 신호가 그 전제 위에 적혀 있기 때문입니다.
예시
웹 색 명세의 두 색 공간
CSS(Cascading Style Sheets) 색 명세는 sRGB(standard Red Green Blue, 표준 적녹청 색 공간)를 미리 정의된 색 공간으로 두고, 그 옆에 srgb-linear 를 따로 둡니다. 명세는 srgb-linear 가 srgb 와 같되 전달 함수만 선형 광량이라 감마 부호화가 없는 것이라고 적습니다. 같은 색 공간을 감마를 건 판과 안 건 판으로 갈라 이름을 두 개 준 것입니다.
명세가 싣고 있는 변환식입니다.
let sign = c < 0 ? -1 : 1;
let abs = math.abs(c);
if (abs <= 0.04045) { cl = c / 12.92; }
else { cl = sign * (math.pow((abs + 0.055) / 1.055, 2.4)); }
명세는 c 가 감마 부호화된 적·녹·청 성분이고 cl 이 그에 대응하는 선형 광량 성분이라고 적습니다. 0.04045 이하는 12.92 로 나누는 직선 구간이고, 그 위는 0.055 를 더해 1.055 로 나눈 뒤 2.4 제곱을 하는 곡선 구간입니다. 성분의 백분율 기준 범위는 0% 가 0.0, 100% 가 1.0 입니다.
OpenGL 프레임버퍼의 sRGB 갱신 모드
Khronos 의 OpenGL 확장 문서는 OpenGL 이 관례적으로 프레임버퍼 색 성분이 선형 색 공간에 저장된다고 가정한다고 적습니다. 특히 프레임버퍼 블렌딩이 선형 연산이라고 적습니다. 같은 문서는 sRGB 색 공간이 어두운 사무실에서 예상되는 전형적인 비선형 모니터 특성에 기반한다고 적습니다. 그 색 공간은 국제전기기술위원회(IEC, International Electrotechnical Commission)가 IEC 61966-2-1 로 표준화했고, 대략 2.2 감마 보정에 대응한다고 적습니다.
이 확장이 더하는 것은 프레임버퍼 갱신과 블렌딩에 걸리는 sRGB 능력입니다. 블렌딩이 꺼져 있고 새 sRGB 갱신 모드가 켜져 있으면, 프래그먼트 컬러링이 만든 적·녹·청의 고정밀 선형 색 성분 값이 프레임버퍼에 쓰이기 전에 sRGB 로 부호화됩니다. 이 확장의 주된 동기는, 프레임버퍼 색 값이 sRGB 로 부호화돼 있다고 가정하도록 설정된 모니터로 주사되는 프레임버퍼에 애플리케이션이 그릴 수 있게 하는 것이라고 문서는 적습니다.
켜고 끄는 상태를 가리키는 토큰은 이렇게 적혀 있습니다.
FRAMEBUFFER_SRGB 0x8DB9
브라우저 비디오 API 의 전달 특성 값
브라우저의 비디오 코덱 API(Application Programming Interface, 응용 프로그램 인터페이스)는 색 공간의 전달 특성을 문자열 하나로 받습니다. MDN(Mozilla Developer Network)이 적는 값 목록입니다.
"bt709" | "smpte170m" | "iec61966-2-1" | "linear" | "pq" | "hlg"
MDN 은 각 값을 어느 규격이 쓰는 전달 특성인지로 설명합니다. bt709 는 BT.709 가 쓰는 것, iec61966-2-1 은 sRGB 가 쓰는 것, linear 는 선형 광량 값이 쓰는 것입니다. 감마를 건 판과 안 건 판이 여기서는 나란히 놓인 선택지가 됩니다. 어느 곡선으로 부호화됐는지를 값과 따로 실어 보내야 화면 쪽이 무엇을 되돌릴지 압니다.
실패
감마 부호화된 값은 겉보기에 그냥 숫자입니다. 그래서 선형 값을 기대하는 연산으로 그대로 흘러들어 갑니다. 규격이 그 자리마다 되돌리기를 따로 규정해 두었다는 것이, 안 되돌리면 결과가 달라진다는 증거입니다.
| 조건 | 그때 나오는 것 |
|---|---|
| 프레임버퍼에 sRGB 로 부호화된 값이 들어 있는데 선형화하지 않고 블렌딩한다 | 섞는 계산이 밝기가 아니라 부호 위에서 돕니다. 규격은 목적지 색 성분을 블렌딩에 쓰기 전에 선형화해야 한다고 규정합니다 |
| sRGB 텍스처를 선형으로 되돌리지 않고 필터링한다 | 표본을 섞는 계산이 부호 위에서 돕니다. 규격은 필터링의 일부로 선형 색 공간으로 변환한다고 규정합니다 |
| 알파 성분까지 같이 되돌린다 | 두 규격 모두 알파는 그대로 두라고 규정합니다. 알파는 빛의 양이 아닙니다 |
블렌딩
Khronos 의 확장 문서는 FRAMEBUFFER_SRGB_EXT 가 켜져 있고 그 드로어블의 FRAMEBUFFER_SRGB_CAPABLE_EXT 상태가 참이면, 고정소수점에서 부동소수점으로 변환된 뒤의 목적지 적·녹·청 색 값이 sRGB 색 공간으로 부호화된 것으로 간주되며 따라서 블렌딩에 쓰이기 전에 선형화되어야 한다고 적습니다. 선형화는 다음 식의 어떤 근사로 이뤄진다고 적습니다. 0.04045 이하이면 cs / 12.92 입니다. 여기서 cs 는 선형화 전 성분 값이고 결과가 cl 입니다.
같은 문서는 되돌리지 않는 경우도 함께 규정합니다. FRAMEBUFFER_SRGB_EXT 가 꺼져 있거나, 드로어블이 sRGB 를 지원하지 않거나, 그 값이 알파 성분이면 cs = cl 로 둡니다. 아무것도 걸지 않는다는 뜻입니다.
되돌리는 단계가 규격 본문에 이렇게 못 박혀 있다는 것은, 그 단계를 건너뛰면 블렌딩 결과가 달라진다는 뜻입니다. 반투명한 것을 겹칠수록 어긋남이 쌓입니다.
텍스처 필터링
같은 레지스트리의 텍스처 확장 문서는 적·녹·청 성분이 필터링의 일부로 sRGB 색 공간에서 선형 색 공간으로 변환된다고 적습니다. 알파 성분은 건드리지 않습니다. 필터링은 텍스처를 확대하거나 축소해서 표본을 섞는 자리입니다. 섞는 자리마다 같은 문제가 되풀이됩니다.
같은 문서는 이상적으로는 구현이 필터링 전에 각 표본마다 이 색 변환을 수행해야 한다고 적습니다. 다만 필터링 뒤에 수행하는 것도 허용된다고 적습니다. 그러면서 그 필터링 후 방식이 필터링 전에 sRGB 에서 변환하는 것보다 못하다고 덧붙입니다. 규격이 허용하는 구현 사이에서도 어느 순서로 되돌리느냐가 결과를 가릅니다.
관련 항목
감마 보정이 걸리는 색 공간
sRGB · srgb-linear · 선형 색 공간 · 색 공간 · Display P3 · Adobe RGB · ProPhoto RGB
감마 보정을 정의하거나 설명하는 표준·문서
IEC 61966-2-1 · ITU-R BT.709 · ITU-R BT.1886 · BT.601 · BT.2100 · CSS · API · MDN · VideoColorSpace
감마 보정을 이루는 구성 요소
OETF · EOTF · 전달 함수 · 감마
감마를 되돌려야 하는 연산
프레임버퍼 · FRAMEBUFFER_SRGB · 알파 블렌딩 · 텍스처 필터링 · 밉맵 · 텍스처
감마 규격을 관리하거나 구현하는 기관·제품
Khronos · IEC · W3C(World Wide Web Consortium, 월드와이드웹 컨소시엄) · OpenGL(Open Graphics Library, 오픈 그래픽스 라이브러리)
감마 보정을 낳은 표시 장치
CRT · 표시 장치 · 모니터
다른 이름: gamma correction · gamma encoding · 감마 인코딩 · 감마 부호화