## Colorspaces

[intro]

Gamma Correction

[to do]

E'R = f(R)

E'G = f(G)

E'B = f(B)

Construction of luminance and color-difference signals

[to do]

E'Y = CoeffR E'R + CoeffG E'G + CoeffB E'B

(E'R - E'Y) = E'R - CoeffR E'R - CoeffG E'G - CoeffB E'B

(E'B - E'Y) = E'B - CoeffR E'R - CoeffG E'G - CoeffB E'B

Re-normalized color-difference signals

The color-difference signals are scaled back to unity range [-0.5;+0.5]:

KB = 0.5 / (1 - CoeffB)

KR = 0.5 / (1 - CoeffR)

PB = KB (E'B - E'Y) = 0.5 (CoeffR / CoeffB) E'R + 0.5 (CoeffG / CoeffB) E'G + 0.5 E'B

PR = KR (E'R - E'Y) = 0.5 E'R + 0.5 (CoeffG / CoeffR) E'G + 0.5 (CoeffB / CoeffR) E'B

Quantization

[to do]

Y' = (Lum. Levels - 1) · E'Y + Lum. Offset

CB = (Chrom. Levels - 1) · PB + Chrom. Offset

CR = (Chrom. Levels - 1) · PR + Chrom. Offset

Rounding to the nearest integer and clamping to the range [0;255] finally yields the digital color components Y'CbCr stored in YUV images.

Example 2.1. ITU-R Rec. BT.601 color conversion

Forward Transformation

```int ER, EG, EB;         /* gamma corrected RGB input [0;255] */
int Y1, Cb, Cr;         /* output [0;255] */

double r, g, b;         /* temporaries */
double y1, pb, pr;

int
clamp (double x)
{
int r = x;      /* round to nearest */

if (r < 0)         return 0;
else if (r > 255)  return 255;
else               return r;
}

r = ER / 255.0;
g = EG / 255.0;
b = EB / 255.0;

y1  =  0.299  * r + 0.587 * g + 0.114  * b;
pb  = -0.169  * r - 0.331 * g + 0.5    * b;
pr  =  0.5    * r - 0.419 * g - 0.081  * b;

Y1 = clamp (219 * y1 + 16);
Cb = clamp (224 * pb + 128);
Cr = clamp (224 * pr + 128);

/* or shorter */

y1 = 0.299 * ER + 0.587 * EG + 0.114 * EB;

Y1 = clamp ( (219 / 255.0)                    *       y1  + 16);
Cb = clamp (((224 / 255.0) / (2 - 2 * 0.114)) * (EB - y1) + 128);
Cr = clamp (((224 / 255.0) / (2 - 2 * 0.299)) * (ER - y1) + 128);
```

Inverse Transformation

```int Y1, Cb, Cr;         /* gamma pre-corrected input [0;255] */
int ER, EG, EB;         /* output [0;255] */

double r, g, b;         /* temporaries */
double y1, pb, pr;

int
clamp (double x)
{
int r = x;      /* round to nearest */

if (r < 0)         return 0;
else if (r > 255)  return 255;
else               return r;
}

y1 = (255 / 219.0) * (Y1 - 16);
pb = (255 / 224.0) * (Cb - 128);
pr = (255 / 224.0) * (Cr - 128);

r = 1.0 * y1 + 0     * pb + 1.402 * pr;
g = 1.0 * y1 - 0.344 * pb - 0.714 * pr;
b = 1.0 * y1 + 1.772 * pb + 0     * pr;

ER = clamp (r * 255); /* [ok? one should prob. limit y1,pb,pr] */
EG = clamp (g * 255);
EB = clamp (b * 255);
```

Table 2.4. enum v4l2_colorspace

IdentifierValueDescriptionChromaticities[a]White PointGamma CorrectionLuminance E'YQuantization
RedGreenBlueY'Cb, Cr
`V4L2_COLORSPACE_SMPTE170M`1NTSC/PAL according to [SMPTE 170M], [ITU BT.601]x = 0.630, y = 0.340x = 0.310, y = 0.595x = 0.155, y = 0.070x = 0.3127, y = 0.3290, Illuminant D65E' = 4.5 I for I ≤0.018, 1.099 I0.45 - 0.099 for 0.018 < I0.299 E'R + 0.587 E'G + 0.114 E'B219 E'Y + 16224 PB,R + 128
`V4L2_COLORSPACE_SMPTE240M`21125-Line (US) HDTV, see [SMPTE 240M]x = 0.630, y = 0.340x = 0.310, y = 0.595x = 0.155, y = 0.070x = 0.3127, y = 0.3290, Illuminant D65E' = 4 I for I ≤0.0228, 1.1115 I0.45 - 0.1115 for 0.0228 < I0.212 E'R + 0.701 E'G + 0.087 E'B219 E'Y + 16224 PB,R + 128
`V4L2_COLORSPACE_REC709`3HDTV and modern devices, see [ITU BT.709]x = 0.640, y = 0.330x = 0.300, y = 0.600x = 0.150, y = 0.060x = 0.3127, y = 0.3290, Illuminant D65E' = 4.5 I for I ≤0.018, 1.099 I0.45 - 0.099 for 0.018 < I0.2125 E'R + 0.7154 E'G + 0.0721 E'B219 E'Y + 16224 PB,R + 128
`V4L2_COLORSPACE_BT878`4Broken Bt878 extents[b], [ITU BT.601]?????0.299 E'R + 0.587 E'G + 0.114 E'B237 E'Y + 16224 PB,R + 128 (probably)
`V4L2_COLORSPACE_470_SYSTEM_M`5M/NTSC[c] according to [ITU BT.470], [ITU BT.601]x = 0.67, y = 0.33x = 0.21, y = 0.71x = 0.14, y = 0.08x = 0.310, y = 0.316, Illuminant C?0.299 E'R + 0.587 E'G + 0.114 E'B219 E'Y + 16224 PB,R + 128
`V4L2_COLORSPACE_470_SYSTEM_BG`6625-line PAL and SECAM systems according to [ITU BT.470], [ITU BT.601]x = 0.64, y = 0.33x = 0.29, y = 0.60x = 0.15, y = 0.06x = 0.313, y = 0.329, Illuminant D65?0.299 E'R + 0.587 E'G + 0.114 E'B219 E'Y + 16224 PB,R + 128
`V4L2_COLORSPACE_JPEG`7JPEG Y'CbCr, see [JFIF], [ITU BT.601]?????0.299 E'R + 0.587 E'G + 0.114 E'B256 E'Y + 16[d]256 PB,R + 128
`V4L2_COLORSPACE_SRGB`8[?]x = 0.640, y = 0.330x = 0.300, y = 0.600x = 0.150, y = 0.060x = 0.3127, y = 0.3290, Illuminant D65E' = 4.5 I for I ≤0.018, 1.099 I0.45 - 0.099 for 0.018 < In/a

[a] The coordinates of the color primaries are given in the CIE system (1931)

[b] The ubiquitous Bt878 video capture chip quantizes E'Y to 238 levels, yielding a range of Y' = 16 … 253, unlike Rec. 601 Y' = 16 … 235. This is not a typo in the Bt878 documentation, it has been implemented in silicon. The chroma extents are unclear.

[c] No identifier exists for M/PAL which uses the chromaticities of M/NTSC, the remaining parameters are equal to B and G/PAL.

[d] Note JFIF quantizes Y'PBPR in range [0;+1] and [-0.5;+0.5] to 257 levels, however Y'CbCr signals are still clamped to [0;255].