Chapter 05

RGB 색공간과 가멋

“R=255, G=0, B=0”은 색이 아니다. 어떤 빨강인지, 백색이 어디인지, 숫자가 빛의 세기와 어떻게 연결되는지를 정해야 비로소 하나의 색이 된다. 이 장에서는 원색 색도와 백색점 네 점에서 RGB→XYZ 행렬을 손으로 유도하고, 그 행렬로 색공간 사이를 변환하며, 표현할 수 없는 색을 어떻게 처리할지를 수치로 따진다.

RGB 색공간을 정하는 세 가지

3장에서 색은 3자극치 XYZ라는 세 숫자로 정해졌다. 디스플레이·카메라·영상 파일이 다루는 RGB 역시 세 숫자이므로, 둘 사이에는 일대일 대응이 있어야 한다. 그 대응을 고정하는 약속이 RGB 색공간(RGB color space)이고, 다음 세 요소로 완전히 정해진다.

  1. 원색 색도(primary chromaticities) — R=(1,0,0), G=(0,1,0), B=(0,0,1)이 각각 어떤 xy 색도인가. 가멋의 모양을 정한다.
  2. 백색점(white point) — R=G=B=1이 어떤 xy 색도인가. 세 원색의 상대 세기(스케일)를 정한다.
  3. 전달 함수(transfer function) — 저장된 코드값 R′G′B′와 빛에 비례하는 선형값 RGB 사이의 비선형 곡선(sRGB 곡선, 감마 2.4, PQ 등). 6장에서 다룬다.

앞의 둘은 선형 대수의 영역이다. 선형 RGB와 XYZ는 3×3 행렬 하나로 오간다. 이 장은 전부 선형 RGB(linear-light RGB)에서 이야기한다. 전달 함수는 행렬 앞뒤에 붙는 채널별 1차원 함수일 뿐이므로, 색역 계산과는 따로 다룰 수 있다.

코드값 R′G′B′ (255, 128, 0) 전달 함수 (EOTF) 채널별 1D 곡선 → 6장 선형 RGB (1, 0.216, 0) M 3×3 XYZ 원색 xy ×3 + 백색 xy (이 장) 곡선 모양만 정한다 색공간 = 원색 색도 + 백색점 + 전달 함수
그림 5-1. RGB 코드값에서 XYZ까지의 경로. 전달 함수는 채널마다 따로 작용하는 비선형 함수이고, 색의 “방향”을 정하는 것은 원색과 백색점으로 만든 3×3 행렬 M이다. 예시 숫자는 sRGB 곡선 기준(128/255 → 0.216).

같은 숫자 (1, 0, 0)이라도 sRGB에서는 xy = (0.640, 0.330)의 빨강이고 Rec.2020에서는 (0.708, 0.292)의 훨씬 진한 빨강이다. 파일이나 신호에 색공간 태그(ICC 프로파일, 비디오의 색 원색 메타데이터)가 없으면 수신 측은 숫자를 해석할 근거가 없어 보통 sRGB로 가정한다. 광색역 사진이 웹에서 “물빠진” 색으로 보이는 흔한 사고가 바로 이 가정 때문이다.

흔한 실수: 전달 함수 적용 전의 값에 행렬 곱하기

3×3 행렬은 선형 RGB에만 의미가 있다. 8비트 코드값(또는 0–1로 나눈 감마 인코딩 값)에 바로 M을 곱하면 무채색은 우연히 맞아도 유채색의 XYZ는 틀린다. 순서는 항상 “디코드(EOTF) → 행렬 → (필요하면) 인코드”다. 이 장의 모든 RGB 값은 선형값이다.

원색과 백색점에서 3×3 행렬 유도

선형 RGB에서 XYZ로 가는 사상은 선형이므로 \( \mathbf{XYZ} = M\,\mathbf{RGB} \)이고, M의 세 열은 각각 R=(1,0,0), G=(0,1,0), B=(0,0,1)의 XYZ다. 문제는 원색에 대해 아는 것이 색도 xy뿐이라는 점이다. 색도는 방향만 알려 주고 크기(휘도)는 알려 주지 않는다. 그 크기를 정해 주는 조건이 백색점이다.

1단계: 색도에서 방향 벡터

원색 i의 색도를 \((x_i, y_i)\)라 하면, Y=1로 둔 3자극치 벡터는 다음과 같다(\(z_i = 1-x_i-y_i\)). 실제 원색의 XYZ는 이 벡터의 스칼라배 \(S_i\mathbf{P}_i\)다.

$$\mathbf{P}_i = \begin{bmatrix} x_i/y_i \\ 1 \\ z_i/y_i \end{bmatrix},\qquad P = \begin{bmatrix} \mathbf{P}_r & \mathbf{P}_g & \mathbf{P}_b \end{bmatrix}$$

2단계: 백색 조건으로 스케일 S 결정

RGB = (1,1,1)이 백색점 \(\mathbf{W}\)(Yw=1)이 되어야 하므로 \(S_r\mathbf{P}_r + S_g\mathbf{P}_g + S_b\mathbf{P}_b = \mathbf{W}\). 이것은 미지수 3개짜리 연립방정식이다.

$$\mathbf{S} = P^{-1}\,\mathbf{W},\qquad \mathbf{W} = \begin{bmatrix} x_w/y_w \\ 1 \\ z_w/y_w \end{bmatrix},\qquad M = P\,\operatorname{diag}(\mathbf{S})$$
Si는 원색 i가 백색을 만들기 위해 내야 하는 휘도다. 백색점이 원색 삼각형 안에 있으면 세 성분 모두 양수다.
O (검정) P_r 방향 P_g 방향 P_b S_r·P_r S_g·P_g S_b·P_b W (백색) sRGB (D65) 수치 P_r = (1.9394, 1, 0.0909) P_g = (0.5000, 1, 0.1667) P_b = (2.5000, 1, 13.1667) W = (0.95046, 1, 1.08906) S = (0.2126, 0.7152, 0.0722) = 각 원색의 휘도 기여 = M의 Y 행 S_r + S_g + S_b = Y_w = 1
그림 5-2. XYZ 공간에서 본 행렬 유도. 색도는 각 원색 벡터의 방향(점선)만 정한다. 세 벡터를 Sr, Sg, Sb배 해서 이어 붙인 끝점이 백색 W에 닿도록 길이를 고르는 것이 2단계다(개념도, 축척 아님).

sRGB를 끝까지 계산하기

sRGB(IEC 61966-2-1, ITU-R BT.709와 같은 원색)의 원색은 R(0.64, 0.33), G(0.30, 0.60), B(0.15, 0.06), 백색은 D65 (0.3127, 0.3290)이다. 1단계 결과를 열로 쌓으면

$$P = \begin{bmatrix} 1.93939 & 0.50000 & 2.50000 \\ 1 & 1 & 1 \\ 0.09091 & 0.16667 & 13.16667 \end{bmatrix},\quad P^{-1} = \begin{bmatrix} 0.6892 & -0.3269 & -0.1060 \\ -0.6932 & 1.3416 & 0.0297 \\ 0.0040 & -0.0147 & 0.0763 \end{bmatrix}$$

백색 \(\mathbf{W} = (0.3127/0.3290,\ 1,\ 0.3583/0.3290) = (0.95046,\ 1,\ 1.08906)\)을 곱하면 \(\mathbf{S} = P^{-1}\mathbf{W} = (0.21264,\ 0.71517,\ 0.07219)\)이다. 각 열에 S를 곱하면 표준에 실린 행렬이 그대로 나온다.

$$M_{\text{sRGB}} = \begin{bmatrix} 0.4124 & 0.3576 & 0.1805 \\ 0.2126 & 0.7152 & 0.0722 \\ 0.0193 & 0.1192 & 0.9505 \end{bmatrix},\qquad M_{\text{sRGB}}^{-1} = \begin{bmatrix} 3.2410 & -1.5374 & -0.4986 \\ -0.9692 & 1.8760 & 0.0416 \\ 0.0556 & -0.2040 & 1.0570 \end{bmatrix}$$
첫 열 검산: 0.21264 × (1.93939, 1, 0.09091) = (0.4124, 0.2126, 0.0193). 행의 합 = W = (0.9505, 1.0000, 1.0890).

Y 행이 곧 휘도 계수인 이유. \(\mathbf{P}_i\)의 Y 성분은 정의상 1이므로 \(M = P\,\mathrm{diag}(\mathbf{S})\)의 둘째 행은 \((S_r, S_g, S_b)\) 자체다. 즉 BT.709의 유명한 휘도 식 \(Y = 0.2126R + 0.7152G + 0.0722B\)는 임의로 정한 가중치가 아니라 “이 원색들로 D65 백색을 만들려면 각자 얼마의 휘도를 내야 하는가”의 답이다. 원색이나 백색점이 바뀌면 이 계수도 바뀐다(Rec.2020: 0.2627 / 0.6780 / 0.0593).

SIMULATOR

원색·백색점 → RGB→XYZ 행렬 실시간 계산

점을 드래그
프리셋
조정할 점
M (선형 RGB → XYZ)—
M⁻¹ (XYZ → 선형 RGB)—
S = Y 행 (휘도 계수)—
검산 · 면적—
해볼 것: ① sRGB에서 G의 y를 0.60→0.70으로 올리면 Y 행의 G 계수가 어떻게 변하는가? ② 백색을 D65에서 D50으로 옮기면 원색이 그대로여도 행렬 전체가 바뀐다. ③ 백색점을 삼각형 밖으로 끌어내 보라. S 성분이 음수가 되어, 그 원색을 “빼야” 백색이 되는 비물리적 상태가 된다. ④ 세 원색을 거의 일직선에 놓으면 P가 특이 행렬에 가까워져 M⁻¹ 원소가 폭주한다.
표준 문서의 역행렬은 왜 미세하게 다른가

IEC 61966-2-1은 XYZ→sRGB 행렬을 3.2406, −1.5372, −0.4986, −0.9689, 1.8758, 0.0415, 0.0557, −0.2040, 1.0570으로 싣고 있다. 이는 4자리로 반올림한 정방향 행렬을 역산한 값이라, 원색·백색 xy에서 바로 계산한 역행렬(3.2410, −1.5374 …)과 10−4 수준에서 차이 난다. 8비트 왕복 변환에서는 차이가 없지만, 16비트 부동소수 파이프라인에서 정·역방향을 서로 다른 출처에서 가져오면 백색 (1,1,1)이 정확히 돌아오지 않는다. 정방향과 역방향은 같은 정의(xy)에서 함께 계산하라. 이 책의 CB.rgb2xyzMatrix도 그렇게 한다.

주요 RGB 색공간 비교

같은 유도 과정에 서로 다른 원색과 백색을 넣으면 실무에서 쓰는 색공간들이 나온다. 아래 표의 면적은 이 페이지가 직접 계산한 값으로, 스펙트럼 궤적은 380–700 nm 단색광 색도를 1 nm 간격으로 이은 다각형(양 끝은 순자주선으로 닫음)이다. 궤적 다각형을 어떻게 잡느냐에 따라 “궤적 대비 %”는 문헌마다 몇 % 포인트씩 다르다.

색공간R (x, y)G (x, y)B (x, y)백색xy 면적궤적 대비 xy궤적 대비 u′v′근거
sRGB / Rec.7090.640, 0.3300.300, 0.6000.150, 0.060D650.112133.6%33.3%IEC 61966-2-1, ITU-R BT.709
Display P30.680, 0.3200.265, 0.6900.150, 0.060D650.152045.6%41.8%SMPTE EG 432-1 원색 + D65
DCI-P30.680, 0.3200.265, 0.6900.150, 0.060DCI (0.314, 0.351)0.152045.6%41.8%SMPTE RP 431-2 (디지털 시네마)
Adobe RGB (1998)0.640, 0.3300.210, 0.7100.150, 0.060D650.151245.3%38.8%Adobe RGB (1998) 사양
Rec.20200.708, 0.2920.170, 0.7970.131, 0.046D650.211963.6%57.3%ITU-R BT.2020, BT.2100
ProPhoto (ROMM)0.7347, 0.26530.1596, 0.84040.0366, 0.0001D500.277083.1%*87.1%*ISO 22028-2 (ROMM RGB)
ACES AP1 (ACEScg)0.713, 0.2930.165, 0.8300.128, 0.044ACES (0.32168, 0.33767)0.225367.6%*59.3%*Academy S-2014-004
ACES AP0 (ACES2065-1)0.7347, 0.26530.0000, 1.00000.0001, −0.0770ACES (0.32168, 0.33767)0.3956118.7%*149.3%*SMPTE ST 2065-1
NTSC 1953 (참고)0.670, 0.3300.210, 0.7100.140, 0.080C (0.310, 0.316)0.158247.5%38.2%FCC 1953 (역사적 기준)

* 삼각형의 일부가 스펙트럼 궤적 밖(가상색)에 있다. 궤적 안쪽만 세면 ProPhoto 79.4%, AP1 66.6%, AP0 100%(궤적 전체 포함)다.

표에서 읽어야 할 공학적 사실은 다음과 같다.

공학자 관점: 행렬값으로 색공간 알아맞히기

미상의 파이프라인에서 행렬만 덤프되었다면 Y 행을 먼저 보라. 0.2126/0.7152/0.0722면 BT.709(D65), 0.2627/0.6780/0.0593이면 BT.2020, 0.2290/0.6917/0.0793이면 Display P3, 0.2973/0.6274/0.0753이면 Adobe RGB, 0.2722/0.6741/0.0537이면 ACEScg다. 반대로 BT.601 Y′CbCr 계수(0.299/0.587/0.114)는 NTSC 1953 원색·C 백색에서 나온 값(0.2990/0.5864/0.1146)을 반올림한 것으로, 오늘날의 SMPTE C/EBU 원색과는 맞지 않는다. 이 불일치가 15장 Y′CbCr 행렬 혼용 문제의 뿌리다.

RGB 공간 사이의 변환

두 RGB 공간 모두 XYZ와 행렬로 연결되므로, 공간 1의 선형 RGB를 공간 2로 옮기는 행렬은 XYZ를 경유한 곱이다.

$$\mathbf{RGB}_2 = M_2^{-1}\, A\, M_1\, \mathbf{RGB}_1,\qquad A = \begin{cases} I & (\text{백색점이 같을 때}) \\ \text{CAT}(\mathbf{W}_1 \to \mathbf{W}_2) & (\text{다를 때}) \end{cases}$$
CAT: 색순응 변환(Bradford 등). 8장에서 유도한다. 이 책에서는 CB.adaptMatrix(W1, W2, 'bradford').

sRGB와 Display P3는 둘 다 D65이므로 A = I이고, 실제 계산값은 다음과 같다.

$$M_{\text{sRGB}\to\text{P3}} = \begin{bmatrix} 0.8225 & 0.1775 & 0.0000 \\ 0.0332 & 0.9668 & 0.0000 \\ 0.0171 & 0.0724 & 0.9105 \end{bmatrix},\qquad M_{\text{P3}\to\text{sRGB}} = \begin{bmatrix} 1.2249 & -0.2249 & 0.0000 \\ -0.0421 & 1.0421 & 0.0000 \\ -0.0196 & -0.0786 & 1.0983 \end{bmatrix}$$
두 공간의 B 원색이 같아 B 입력은 B 출력에만 들어간다(셋째 열이 (0,0,·)). 각 행의 합은 1: 백색이 백색으로 간다.

P3의 순수 빨강 (1, 0, 0)을 sRGB로 옮기면 첫째 열이 그대로 나와 (1.2249, −0.0421, −0.0196)이 된다. R이 1을 넘고 G, B가 음수다. 이 색은 sRGB로 표현할 수 없는 색이며, 이 숫자가 그 사실을 정량적으로 알려 준다. Rec.2020 ↔ sRGB도 같은 방식으로 \(M_{2020\to709}\) 첫 행이 (1.6605, −0.5876, −0.0728)이다.

백색점이 다를 때 A를 빼먹으면

sRGB(D65) → ProPhoto(D50)를 \(M_2^{-1}M_1\)로만 계산하면 sRGB 백색 (1,1,1)이 ProPhoto에서 (0.968, 1.013, 1.320)이 된다. 수학적으로는 “같은 XYZ”이므로 측색적으로 옳지만, ProPhoto 쪽 시스템은 D50을 백색으로 보므로 화면에서 푸르게 보인다. 실무(ICC의 상대 색도 인텐트)에서는 Bradford 순응을 끼워 (1,1,1)→(1,1,1)이 되게 한다. 이때 행렬은 첫 행이 (0.5293, 0.3302, 0.1406)이 되고 각 행의 합이 1이 된다. 어느 쪽이 맞는지는 “관찰자가 어느 백색에 적응해 있는가”의 문제이고, 16장의 렌더링 인텐트가 이를 정한다.

SIMULATOR

선형 RGB 변환기: 한 색을 여러 공간에서 보기

입력 공간
백색점이 다를 때
XYZ (입력 백색 기준, Yw=1)—
xy 색도—
입력 → sRGB 행렬—
해볼 것: ① P3 (1,0,0)이 sRGB에서 음수를 갖는 것을 확인하고 G를 0.05쯤 올리면 sRGB 안으로 들어오는지 보라. ② 입력을 2020 (0,1,0)으로 바꾸면 sRGB에서 R ≈ −0.59가 된다. ③ ProPhoto 입력에서 “순응 없음”을 고르면 (1,1,1)이 sRGB에서 (1,1,1)이 아니다. ④ 무채색(R=G=B)은 백색점이 같은 공간끼리 항상 같은 값으로 간다. 색견본은 sRGB 화면에 표시되므로 가멋 밖이면 클리핑되어 보인다.

가멋 면적과 커버리지

세 원색의 양의 조합(0 ≤ R, G, B)으로 만들 수 있는 색도는 원색 삼각형 내부다. 그래서 xy 색도도 위의 삼각형을 2D 가멋(gamut, 색역)이라 부르고, 그 크기를 숫자 하나로 요약하려는 시도가 디스플레이 사양서의 “NTSC 대비 72%”, “DCI-P3 95%” 같은 표기다. 이 숫자들은 서로 전혀 다른 두 가지를 섞어 쓴다.

기준 가멋 (면적 1.00) 디스플레이 가멋 (면적 1.05) 면적 비 = 105% “기준보다 넓다”처럼 보인다 커버리지 = 교집합 / 기준 ≈ 80% 기준의 아래쪽 꼭짓점 영역을 못 낸다 교집합 = Sutherland–Hodgman (볼록 다각형 클리핑)
그림 5-3. 면적 비와 커버리지. 디스플레이 가멋(점선)이 기준(채움)보다 넓어도 위치가 어긋나 있으면 기준 색의 일부를 재현할 수 없다. 사양서의 “%”가 둘 중 무엇인지, 어느 좌표계(xy, u′v′)인지 밝히지 않으면 비교할 수 없다(개념도, 수치는 예시).

삼각형 면적은 신발끈 공식으로, 교집합은 볼록 다각형 클리핑으로 구한다. Sutherland–Hodgman 알고리즘은 대상 다각형(subject)을 클립 다각형의 각 변이 만드는 반평면으로 차례로 잘라 낸다. 클립 다각형이 볼록이기만 하면 대상은 오목해도 된다. 그래서 스펙트럼 궤적(대상)을 원색 삼각형(클립)으로 잘라 “삼각형 중 실재색 부분”도 같은 코드로 계산한다.

$$|G| = \tfrac12\Big|\sum_{i} (x_i\,y_{i+1} - x_{i+1}\,y_i)\Big|,\qquad \text{inside}(p; a\to b) \iff (b-a)\times(p-a) \ge 0$$
반시계 방향 클립 다각형에서 변 a→b의 왼쪽이 안쪽이다. 한 변으로 자를 때 대상 다각형의 각 변 P→Q에 대해 P가 안이면 P를 남기고, P와 Q가 경계를 넘나들면 교점 \(P + t(Q-P),\ t = s_P/(s_P - s_Q)\)를 추가한다.

xy vs u′v′. xy 색도도는 녹색 영역이 지각적으로 과장되어 있다(4장의 맥아담 타원). 그래서 녹색 쪽으로 넓어진 가멋은 xy 면적에서 실제 체감보다 크게 나온다. CIE 1976 u′v′는 이를 일부 보정한다. 같은 P3를 놓고 xy에서는 sRGB의 1.36배, u′v′에서는 1.26배다. “P3는 sRGB보다 약 25% 넓다”는 흔한 표현은 u′v′ 기준이다.

SIMULATOR

가멋 비교: 면적, 궤적 대비, 커버리지

좌표계
커버리지 기준
표시할 공간
P3 ÷ sRGB 면적 (xy / u′v′)—
sRGB ÷ NTSC 면적 (xy / u′v′)—
궤적 면적 (xy / u′v′)—
해볼 것: ① 기준을 NTSC로 두고 sRGB를 보라. 면적 비는 70.8%인데 NTSC를 덮는 비율(커버리지)은 68.5%이고, 반대로 NTSC는 sRGB의 96.7%만 덮는다(sRGB 청색이 NTSC 밖으로 나간다). “72% NTSC = sRGB 100%”는 성립하지 않는다. ② u′v′로 바꾸면 같은 sRGB가 NTSC 대비 87.2%가 된다. ③ ProPhoto와 AP0를 켜고 궤적 밖으로 나간 부분을 확인하라. 표의 “실재색 비율” 열이 그 부분을 뺀 값이다.
공학자 관점: 사양서 수치 읽는 법

디스플레이 측정 보고서에는 ① 좌표계(xy/u′v′), ② 면적 비인지 커버리지인지, ③ 기준 원색 정의(DCI-P3는 원색만 쓰고 백색은 무시하는 것이 관례), ④ 측정 조건(최대 밝기, 측정 패턴 크기)을 함께 적어야 한다. 근래의 업계 관행은 “u′v′ 커버리지”를 쓰는 쪽으로 옮겨 가고 있으며, 단순 “NTSC %”는 1953년 원색이 현대 콘텐츠의 어느 표준과도 맞지 않으므로 마케팅 숫자 이상의 의미가 없다.

2D 가멋에서 3D 가멋 부피로

색도 삼각형은 밝기를 버린 투영이다. 실제로 장치가 낼 수 있는 색은 RGB 단위 큐브 [0,1]³ 전체를 행렬 M으로 옮긴 입체이고, XYZ에서는 평행육면체가 된다. 이 입체를 지각적으로 균일한 CIELAB(7장)으로 옮기면 휘어진 다면체가 되며, 그 부피(단위 ΔE³)가 “구별 가능한 색의 수”에 비례하는 더 정직한 가멋 척도다.

부피는 표면 삼각형 메시에서 발산 정리로 계산한다. 원점과 각 삼각형이 이루는 사면체의 부호 있는 부피를 더하면 된다.

$$V = \frac16 \sum_{\text{삼각형 } k} \mathbf{a}_k \cdot (\mathbf{b}_k \times \mathbf{c}_k)$$
\(\mathbf{a},\mathbf{b},\mathbf{c}\): 큐브 각 면을 n×n으로 나눈 격자 꼭짓점을 Lab로 옮긴 좌표. 면의 방향(바깥 법선)을 일관되게 유지해야 한다.

이렇게 구한 CIELAB 부피(D65 기준, 각 면 48×48 분할)는 sRGB 약 8.19×10⁵, Display P3 1.23×10⁶, Adobe RGB 1.19×10⁶, Rec.2020 1.85×10⁶이다. sRGB 대비 비율은 P3 1.50, Rec.2020 2.26으로 xy 면적 비(1.36, 1.89)보다 크다. 고채도 색이 밝은 쪽까지 살아 있는지가 부피에는 반영되지만 색도 면적에는 반영되지 않기 때문이다. 같은 이유로 RGBW 패널처럼 백색 서브픽셀로 밝기를 올린 디스플레이는 색도 삼각형은 같아도 고채도·고휘도 영역의 부피가 작다.

3D

RGB 큐브를 CIELAB·XYZ에 올려 보기

드래그로 회전 · 휠로 확대
좌표
sRGB Lab 부피—
P3 Lab 부피—
Rec.2020 Lab 부피—
해볼 것: ① XYZ 모드에서 sRGB 입체가 평행육면체(선형 사상)임을 확인하라. ② Lab 모드에서 위(L*=100)에서 내려다보면 sRGB 청색 꼭짓점이 L*≈32로 낮게 있고, 노랑은 L*≈97로 백색 바로 옆이다. ③ Rec.2020 와이어가 sRGB 입체를 녹색·청록 방향으로 크게 감싸는 것을 보라. 색 입체의 표면 색은 sRGB이므로 화면에서 정확하다.

가멋 밖의 색: 음수와 1 초과

목표 공간의 행렬 \(M^{-1}\)은 모든 XYZ에 대해 RGB를 계산해 준다. 다만 그 결과가 [0,1]³ 밖일 수 있다. 두 경우는 성격이 다르다.

R G B 안: R,G,B ≥ 0 밖: R < 0 G–B 변의 반대편 Rec.2020 G → sRGB 선형값 R = −0.5876 G = 1.1329 B = −0.1006 음수: 색도가 밖 G > 1: 너무 밝음 (둘 다 발생)
그림 5-4. RGB 성분의 부호는 색도의 무게중심 좌표 부호와 같다(각 원색의 스케일 Si>0이므로). G–B 변을 넘어간 점은 R이 음수가 된다. Rec.2020의 순수 녹색은 sRGB에서 R, B가 모두 음수다.

음수 RGB를 그대로 저장할 수 있는 형식(OpenEXR 반정밀 부동소수, scRGB, 확장 sRGB)도 있다. Display P3 콘텐츠를 확장 sRGB 값으로 넘기는 운영체제 API가 그 예다. 그러나 최종적으로 패널 구동값을 만들 때는 반드시 [0,1]로 보내야 하고, 그 방법이 가멋 매핑(gamut mapping)이다.

흔한 실수: 음수를 정수 변환에서 0으로 조용히 자르기

float→uint8 변환 함수 대부분은 음수를 0으로, 1 초과를 255로 포화시킨다. 이것이 사실상 “채널별 클리핑”이라는 가멋 매핑을 아무도 결정하지 않은 채 적용한 것이다. 광색역 이미지를 sRGB로 낼 때 고채도 영역의 계조가 뭉개지고 색상이 틀어지는 원인이 대부분 여기 있다.

가멋 매핑 방법 비교

가멋 밖 색을 안으로 옮기는 방법은 “무엇을 지킬 것인가”로 구분된다. 이 장에서 비교하는 네 가지는 다음과 같다.

  1. 채널별 클리핑(per-channel clip): 각 성분을 [0,1]로 자른다. 가장 가깝지만 색상(hue)과 밝기가 함께 움직이고, 가멋 밖 색들이 경계의 한 점으로 뭉친다.
  2. 휘도 보존 탈채도: 같은 휘도 Y의 무채색 (Y,Y,Y) 쪽으로 직선으로 끌어당긴다. 색도도에서 백색점을 향한 직선 위를 움직이므로 주파장이 보존된다. \( \mathbf{c}' = Y + \alpha(\mathbf{c} - Y),\ \ \alpha = \max\{a \in [0,1] : \mathbf{c}' \in [0,1]^3\}\)
  3. 색상 보존 클리핑: 지각 균일 공간 OKLCh(7장)에서 명도 L과 색상 h를 고정하고, 채도 C만 경계까지 줄인다(이분 탐색).
  4. 채도 압축(soft-knee compression): 3과 같은 방향이지만, 경계 근처의 일정 비율(문턱 t) 바깥에서부터 부드럽게 압축해 원본 가멋 경계(lim)가 목표 경계(1)에 닿도록 한다. 가멋 안쪽 색도 조금 바뀌지만 계조가 유지된다. ACES 1.3의 참조 가멋 압축(RGC)과 같은 꼴의 함수를 쓴다.
$$d = \frac{C}{C_{\max}^{\text{dst}}(L,h)},\quad f(d) = \begin{cases} d & d \le t \\ t + \dfrac{s\,x}{(1 + x^{p})^{1/p}},\ x = \dfrac{d-t}{s} & d \gt t \end{cases},\quad s = \frac{\ell - t}{\left[\left(\frac{\ell - t}{1-t}\right)^{p} - 1\right]^{1/p}}$$
\(\ell = C_{\max}^{\text{src}}/C_{\max}^{\text{dst}}\): 그 명도·색상에서 원본(Rec.2020) 경계가 목표(sRGB) 경계의 몇 배인가. s는 \(f(\ell) = 1\)이 되도록 고른다. p = 1.2.
LC cusp 원본 경계 목표 가멋 원본 색 L·h 고정 채널 클립 출력 C/C_max 입력 C/C_max 1 (목표 경계) t ℓ 소프트 니 하드 클립
그림 5-5. 왼쪽: 한 색상 단면(명도–채도 평면)의 목표 가멋과 원본 가멋. 색상 보존 클리핑은 L을 고정한 채 수평으로 경계까지 이동하고, 채널별 클리핑은 명도·채도(그리고 색상)를 함께 바꾼다. 오른쪽: 하드 클립은 경계 밖 색을 모두 1로 보내 구분이 사라지고, 소프트 니는 문턱 t부터 압축해 원본 경계 ℓ을 1에 맞춘다.

구체적 숫자로 보자. Rec.2020의 순수 녹색 (0,1,0)은 CIELAB(D65)에서 (85.9, −172.3, 116.6)이고, sRGB 선형값은 (−0.588, 1.133, −0.101)이다. 채널별 클리핑은 sRGB 녹색 (0,1,0) = Lab (87.7, −86.2, 83.2)으로 보내 ΔE00 = 12.3이고, 휘도 보존은 (0, 0.922, 0.261)로 ΔE00 = 17.3, OKLCh 색상 보존은 (0, 0.849, 0.210)으로 ΔE00 = 17.0이다. ΔE00만 보면 클리핑이 가장 좋다. 그러나 아래 시뮬레이터에서 보듯 클리핑은 색상에 따라 CIELAB 색상각이 최대 10–20° 틀어지고, 채도가 다른 원본 색들이 하나의 출력으로 합쳐져 계조가 사라진다. 단일 색의 색차 최소화와 이미지 전체의 자연스러움은 다른 목표다.

SIMULATOR

가멋 매핑: Rec.2020 → sRGB, 방법별 결과와 ΔE00

채널 클리핑 평균/최대—
휘도 보존 평균/최대—
색상 보존 평균/최대—
채도 압축 평균/최대—
sRGB 밖 비율—
램프 끝 구분 ΔE00 (채도 0.8↔1.0)—
원본 링: OKLCh에서 명도 L을 고정하고 색상 h를 0–360° 돌리며, 채도는 그 (L,h)에서 Rec.2020 경계 채도의 지정 비율로 둔다. 원본 띠는 화면(sRGB)에서 클리핑되어 보인다. 해볼 것: ① 채도 0.5–0.6에서는 일부 색상만 sRGB 밖이다. 이때 채도 압축은 가멋 안 색도 바꾸므로 평균 ΔE가 커진다. ② 아래 램프에서 채널 클리핑은 채도 끝부분이 한 색으로 뭉치지만(구분 ΔE가 작다), 채도 압축은 끝까지 구분된다. ③ 문턱 t를 0.95로 올리면 압축이 하드 클립에 가까워진다.
실무 선택 가이드

사진·영상 전체 이미지에는 계조를 지키는 압축형(소프트 니, ACES RGC, ICC 지각 인텐트)을, 로고·코퍼레이트 컬러처럼 개별 색의 정확도가 중요한 경우에는 ΔE 최소 클리핑(ICC 상대 색도 인텐트 + 블랙 포인트 보정)을 쓴다. 어느 쪽이든 매핑은 지각 공간(OKLCh, CAM16-UCS, ICtCp)에서 하는 것이 선형 RGB에서 하는 것보다 색상 이동이 작다. 색상 보존 클리핑도 “OKLab에서 보존”일 뿐이라 CIELAB 색상각으로는 수 °가 움직일 수 있다는 점에 유의하라.

원색 선택의 트레이드오프

그렇다면 왜 모두 AP0나 ProPhoto처럼 넓은 공간을 쓰지 않는가. 두 가지 비용이 있다.

① 양자화 간격. 같은 비트 수 N으로 더 넓은 공간을 나누면 코드값 한 단계(1 LSB)가 더 큰 색 차이가 된다. sRGB 안에 있는 색만 다루는 콘텐츠라도 Rec.2020 컨테이너에 담으면 코드값 공간의 상당 부분(sRGB 밖 영역)을 쓰지 않으면서 간격만 넓어진다. 그래서 BT.2020은 10비트 또는 12비트를 규정하고, ProPhoto는 16비트로 다루는 것이 관례다.

좁은 가멋 (sRGB) 넓은 가멋 (Rec.2020) sRGB 안 색이 쓰는 코드 구간 sRGB 콘텐츠에선 미사용 같은 2^N 코드 → 간격 Δ ∝ (가멋 폭) / (2^N − 1)
그림 5-6. 양자화 간격의 개념. 같은 수의 코드(눈금)로 넓은 범위를 나누면 한 눈금의 색 차이가 커진다(1차원 개념도). 실제 비율은 색의 위치에 따라 다르며 아래 시뮬레이터가 ΔE00으로 계산한다.
SIMULATOR

1 LSB의 색 차이: 공간과 비트 수

통계
표시할 비트 수
sRGB—
Display P3—
Adobe RGB—
Rec.2020—
ProPhoto—
방법: sRGB 큐브 안에서 고정 시드로 뽑은 1000개 색을 각 공간(ProPhoto는 Bradford로 D50 순응)의 N비트 코드로 양자화한 뒤, 한 채널을 1 LSB 바꿨을 때의 ΔE00을 구한다. 원색의 영향만 보기 위해 전달 함수는 모든 공간에 sRGB 곡선을 썼다(실제 Adobe RGB·ProPhoto 곡선은 다르다, 6장). 해볼 것: 8비트에서 Rec.2020의 평균 간격이 sRGB의 약 1.5배임을 확인하고, 10비트 Rec.2020이 8비트 sRGB보다 촘촘한지 보라.

② 물리적 원색의 구현. 원색이 스펙트럼 궤적에 가까울수록 원색 빛의 대역폭이 좁아야 한다. Rec.2020을 100% 내려면 630/532/467 nm의 사실상 단색광, 즉 레이저가 필요하다. 레이저 원색은 다음 문제를 갖는다.

그래서 실제 광색역 패널(QD-OLED, 양자점 LCD)은 Rec.2020을 컨테이너로 쓰면서 실제 원색은 P3 근처~Rec.2020 커버리지 80–90%대에 머무는 것이 보통이다. 원색 스펙트럼과 패널 특성화는 13장에서 다룬다.

공학자 관점: 작업 공간 고르기

합성·렌더링은 ACEScg(AP1)나 선형 Rec.2020, 보관·교환은 AP0(ACES2065-1, 16비트 half float), 웹 배포는 sRGB 또는 Display P3(태그 필수), HDR 방송은 Rec.2020 + PQ/HLG 10비트(14장)가 일반적이다. 정수 8비트로 넓은 공간을 쓰는 것이 가장 나쁜 조합이다. 넓은 공간은 부동소수 또는 최소 10비트와 짝지어라.

핵심 정리

  1. RGB 색공간 = 원색 색도 + 백색점 + 전달 함수. 앞의 둘이 선형 RGB↔XYZ 3×3 행렬을 정하고, 전달 함수는 그 앞뒤의 채널별 곡선이다.
  2. \(M = P\,\mathrm{diag}(P^{-1}\mathbf{W})\). sRGB(D65)에서 S = (0.2126, 0.7152, 0.0722)이고, M = [0.4124 0.3576 0.1805; 0.2126 0.7152 0.0722; 0.0193 0.1192 0.9505].
  3. M의 Y 행은 S 자체이므로 휘도 계수는 원색과 백색점에서 결정된다(709: 0.2126/0.7152/0.0722, 2020: 0.2627/0.6780/0.0593).
  4. 공간 변환은 \(M_2^{-1} A M_1\). 백색점이 다르면 A에 색순응(Bradford 등)을 넣는다. sRGB→P3 첫 행은 (0.8225, 0.1775, 0), P3 빨강은 sRGB에서 (1.2249, −0.0421, −0.0196)이다.
  5. 가멋 “%”는 면적 비인지 커버리지(교집합/기준)인지, xy인지 u′v′인지에 따라 크게 달라진다. P3/sRGB는 xy 1.36배, u′v′ 1.26배다. 교집합은 Sutherland–Hodgman 클리핑으로 계산한다.
  6. 2D 색도 면적보다 3D(CIELAB) 부피가 재현 가능 색의 수를 더 잘 나타낸다. sRGB 약 8.2×10⁵ ΔE³, Rec.2020 약 1.85×10⁶ ΔE³.
  7. 음수 RGB는 색도가 가멋 밖, 1 초과는 너무 밝음을 뜻한다. 매핑 방법(채널 클립, 휘도 보존, 색상 보존, 소프트 니)은 단일 색 ΔE00과 색상·계조 보존 사이에서 서로 다른 절충을 한다.
  8. 넓은 가멋은 같은 비트 수에서 양자화 간격을 키우고(8비트 Rec.2020 ≈ sRGB의 1.5배), 실제 원색 구현에는 협대역(레이저) 광원의 스페클·관찰자 메타머리즘 문제가 따른다.

확인 퀴즈

1. RGB→XYZ 행렬을 만들 때 원색 xy 세 점만으로는 부족하고 백색점이 필요한 이유는?

미지수 Sr, Sg, Sb 3개를 “(1,1,1) → W” 조건 3개(X, Y, Z)로 푼다. 그래서 \(\mathbf{S} = P^{-1}\mathbf{W}\)다.

2. sRGB 행렬의 둘째 행이 (0.2126, 0.7152, 0.0722)인 근본 이유는?

각 원색이 D65 백색을 만들기 위해 내야 하는 휘도가 곧 휘도 계수다. 원색이나 백색이 바뀌면 함께 바뀐다.

3. Display P3와 DCI-P3에 대해 옳은 것은?

Display P3는 D65, DCI-P3는 DCI 백색 (0.314, 0.351)이다. Y 행도 0.2290/0.6917/0.0793 대 0.2095/0.7216/0.0689로 다르다.

4. ProPhoto RGB와 ACES AP0가 “가상 원색”을 쓰는 주된 이점은?

원색이 궤적 밖에 있으면 삼각형이 궤적을 (거의) 감싼다. 대신 코드값의 일부는 존재하지 않는 색에 쓰여 낭비되고 양자화 간격은 커진다.

5. sRGB(D65) 선형값을 ProPhoto(D50)로 옮길 때 \(M_2^{-1}M_1\)만 쓰면 sRGB 백색 (1,1,1)은?

측색적으로는 같은 XYZ지만, D50에 적응한 시스템에서는 D65가 푸른 색이다. Bradford 순응을 넣으면 (1,1,1)→(1,1,1)이 된다.

6. 어떤 모니터가 “NTSC 대비 면적 105%”라고 한다. 반드시 참인 것은?

면적 비는 위치를 무시한다. 커버리지는 교집합으로 따로 계산해야 하며, xy와 u′v′ 면적 비도 다르다(sRGB: xy 70.8%, u′v′ 87.2% NTSC).

7. Sutherland–Hodgman 알고리즘으로 “스펙트럼 궤적 ∩ 원색 삼각형”을 계산할 때 올바른 역할 배정은?

S–H는 클립 다각형이 볼록이어야 한다. 대상은 오목해도 된다. 삼각형은 항상 볼록이므로 클립으로 쓰면 안전하다.

8. Rec.2020 녹색을 sRGB로 옮겼더니 (−0.588, 1.133, −0.101)이었다. 해석으로 옳은 것은?

스케일은 부호를 바꾸지 못한다. 음수는 색도 문제, 1 초과는 밝기 문제다. 이 색은 둘 다 갖는다.

9. 가멋 매핑에서 채널별 클리핑이 평균 ΔE00은 작은데도 이미지에서 기피되는 이유는?

개별 색 정확도와 이미지 구조 보존은 다른 목표다. 소프트 니 압축은 가멋 안쪽 색까지 조금 바꾸는 대가로 차이를 유지한다.

10. 같은 8비트로 sRGB 콘텐츠를 Rec.2020 컨테이너에 담으면?

그래서 BT.2020은 10/12비트를 규정한다. 넓은 공간은 높은 비트 깊이 또는 부동소수와 짝지어야 한다.