Macaw.Layers.Color.Vision (macaw_layers v0.2.2)

Copy Markdown View Source

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"

Summary

Types

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

Functions

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

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

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.

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

Types

deficiency()

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

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

Functions

deficiencies()

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

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

matrix(deficiency)

@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(text, deficiency)

@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(color, deficiency)

@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.