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
Functions
@spec deficiencies() :: [deficiency(), ...]
The deficiencies the model simulates: [:protanopia, :deuteranopia, :tritanopia].
@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]
@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)"/>|
@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.