# `Macaw.Layers.Color.Vision`
[🔗](https://github.com/dcoai/macaw_layers/blob/v0.2.2/lib/macaw/layers/color/vision.ex#L1)

Color-vision simulation: how a color reads to a person with one of the three
dichromacies (spec/04 §1.5, visualize D-139).

The model is Machado, Oliveira and Fernandes (2009), "A Physiologically-based Model for
Simulation of Color Vision Deficiency", *IEEE Transactions on Visualization and Computer
Graphics* 15(6), 1291–1298, at severity 1.0. A color is decoded from sRGB to linear RGB,
multiplied by the deficiency's matrix, clamped to `0..1` and encoded back; its opacity is
kept. Each matrix's rows sum to 1, so a gray is its own simulation.

It is a transform for judging a palette by eye — an editor draws a theme's ramps and its
preview through it — and nothing in the library draws through it on its own.

Ported from visualize's `Visualize.Color.Vision`.

## Examples

    iex> red = Macaw.Layers.Color.parse("#ff0000")
    iex> Macaw.Layers.Color.Vision.simulate(red, :protanopia) |> Macaw.Layers.Color.to_hex()
    "#6d5f00"
    iex> gray = Macaw.Layers.Color.parse("#808080")
    iex> Macaw.Layers.Color.Vision.simulate(gray, :tritanopia) |> Macaw.Layers.Color.to_hex()
    "#808080"

# `deficiency`

```elixir
@type deficiency() :: :protanopia | :deuteranopia | :tritanopia
```

A dichromacy the model simulates, or `:none` for the color as it is.

# `deficiencies`

```elixir
@spec deficiencies() :: [deficiency(), ...]
```

The deficiencies the model simulates: `[:protanopia, :deuteranopia, :tritanopia]`.

# `matrix`

```elixir
@spec matrix(deficiency()) :: [[float()]]
```

The deficiency's matrix over linear RGB, as three rows (Machado et al. 2009, severity 1.0).

    iex> Macaw.Layers.Color.Vision.matrix(:deuteranopia) |> hd()
    [0.367322, 0.860646, -0.227968]

# `recolor`

```elixir
@spec recolor(String.t(), deficiency() | :none) :: String.t()
```

The text with every `#rrggbb` and `#rgb` color literal replaced by its simulation, as
`#rrggbb` — an SVG's fills and strokes, a style's colors. A `#` that is a reference,
`url(#id)`, is left alone, and so is everything that is not a color; `:none` is the text.

    iex> Macaw.Layers.Color.Vision.recolor(~s|<rect fill="#ff0000" mask="url(#bad)"/>|, :protanopia)
    ~s|<rect fill="#6d5f00" mask="url(#bad)"/>|

# `simulate`

```elixir
@spec simulate(Macaw.Layers.Color.t(), deficiency() | :none) :: Macaw.Layers.Color.t()
```

The color as the deficiency sees it, its opacity kept; `:none` is the color itself.
Any other atom raises `ArgumentError`.

---

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