# `Color.CAM16UCS`

CAM16-UCS perceptual color space.

CAM16 is a full color appearance model (Li et al. 2017, an update of
CIECAM02). CAM16-UCS is its uniform-color-space projection —
a `(J', a', b')` triple where equal Euclidean distance corresponds
to equal perceptual difference, even better than CIELAB.

Conversions assume standard default viewing conditions:

* Reference white: D65.

* Adapting luminance `L_A = 64 / π / 5 ≈ 4.074` cd/m².

* Background relative luminance `Y_b = 20`.

* Average surround (`F = 1.0`, `c = 0.69`, `N_c = 1.0`).

If you need non-default viewing conditions you can pass them as
options.

# `t`

```elixir
@type t() :: %Color.CAM16UCS{
  a: float() | nil,
  alpha: Color.Types.alpha(),
  b: float() | nil,
  j: float() | nil
}
```

A `Color.CAM16UCS` colour. The CAM16-UCS uniform space coordinates:
`j` is lightness in `[0, 100]`, `a` and `b` are red-green and
yellow-blue chromatic coordinates.

# `from_xyz`

Converts CIE `XYZ` (D65, `Y ∈ [0, 1]`) to CAM16-UCS.

### Arguments

* `xyz` is a `Color.XYZ` struct.

* `options` is a keyword list.

### Options

* `:viewing_conditions` is a map with `:xyz_w`, `:la`, `:yb`, and
  `:surround`. Defaults to D65 / `L_A = 4.074` / `Y_b = 20` / average.

### Returns

* A `Color.CAM16UCS` struct where `j` is `J'`, `a` is `a'`, `b` is
  `b'`.

### Examples

    iex> {:ok, ucs} = Color.CAM16UCS.from_xyz(%Color.XYZ{x: 0.95047, y: 1.0, z: 1.08883, illuminant: :D65, observer_angle: 2})
    iex> {Float.round(ucs.j, 2), :math.sqrt(ucs.a * ucs.a + ucs.b * ucs.b) < 3.0}
    {100.0, true}

# `to_xyz`

Converts CAM16-UCS to CIE `XYZ` (D65, `Y ∈ [0, 1]`).

### Arguments

* `ucs` is a `Color.CAM16UCS` struct.

* `options` is a keyword list (see `from_xyz/2`).

### Returns

* A `Color.XYZ` struct tagged D65/2°.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
