TermUI.Color.Converter (TermUI v1.0.0)
View SourceColor conversion algorithms for terminal color degradation.
This module provides functions to convert RGB colors to various terminal color palettes, enabling graceful degradation from 24-bit true color to 256-color, 16-color, or monochrome modes.
Color Modes
| Mode | Colors | Use Case |
|---|---|---|
:true_color | 16.7M | Modern terminals (24-bit RGB) |
:color_256 | 256 | Most Unix terminals |
:color_16 | 16 | Basic terminal compatibility |
:monochrome | 2 | Minimal terminals, accessibility |
Conversion Algorithms
RGB to 256-color
Uses the xterm 256-color palette:
- Indices 16-231: 6x6x6 color cube
- Indices 232-255: 24-step grayscale ramp
Near-grayscale colors are mapped to the grayscale ramp for better fidelity.
RGB to 16-color
Uses weighted Euclidean distance with perceptual luminance weights:
- Red: 0.299
- Green: 0.587
- Blue: 0.114
These weights match human eye sensitivity, producing better color matches than naive RGB distance.
Examples
iex> TermUI.Color.Converter.rgb_to_256({255, 0, 0})
196
iex> TermUI.Color.Converter.rgb_to_16({255, 0, 0}, :fg)
91 # bright red foreground
iex> TermUI.Color.Converter.rgb_to_16({0, 128, 0}, :bg)
42 # green background
Summary
Functions
Checks if an RGB color is close to grayscale.
Returns the perceptual luminance weights used for color distance.
Converts RGB values to a 16-color ANSI code.
Converts RGB values to a 256-color palette index.
Functions
@spec grayscale?({0..255, 0..255, 0..255}) :: boolean()
Checks if an RGB color is close to grayscale.
A color is considered grayscale if the difference between its R, G, and B components is less than the grayscale threshold (10).
Parameters
rgb- Tuple{r, g, b}with values 0-255
Returns
Boolean indicating if the color is near-grayscale.
Examples
iex> TermUI.Color.Converter.grayscale?({128, 128, 128})
true
iex> TermUI.Color.Converter.grayscale?({128, 130, 127})
true
iex> TermUI.Color.Converter.grayscale?({255, 0, 0})
false
Returns the perceptual luminance weights used for color distance.
These weights match human eye sensitivity:
- Red: 0.299
- Green: 0.587
- Blue: 0.114
Returns
Tuple {r_weight, g_weight, b_weight}.
@spec rgb_to_16({0..255, 0..255, 0..255}, :fg | :bg) ::
30..37 | 40..47 | 90..97 | 100..107
Converts RGB values to a 16-color ANSI code.
Uses perceptually-weighted Euclidean distance to find the closest color in the 16-color ANSI palette.
Parameters
rgb- Tuple{r, g, b}with values 0-255type-:fgfor foreground or:bgfor background
Returns
Integer representing the ANSI color code:
- Foreground: 30-37 (normal) or 90-97 (bright)
- Background: 40-47 (normal) or 100-107 (bright)
Examples
iex> TermUI.Color.Converter.rgb_to_16({255, 0, 0}, :fg)
91 # bright red
iex> TermUI.Color.Converter.rgb_to_16({0, 128, 0}, :bg)
42 # green background
iex> TermUI.Color.Converter.rgb_to_16({64, 64, 64}, :fg)
90 # dark gray (bright black)
@spec rgb_to_256({0..255, 0..255, 0..255}) :: 0..255
Converts RGB values to a 256-color palette index.
Uses the xterm 256-color palette:
- Indices 16-231: 6x6x6 color cube
- Indices 232-255: 24-step grayscale ramp
Near-grayscale colors (where R, G, B differ by less than 10) are mapped to the grayscale ramp for better fidelity.
Parameters
rgb- Tuple{r, g, b}with values 0-255
Returns
Integer 0-255 representing the palette index.
Examples
iex> TermUI.Color.Converter.rgb_to_256({255, 0, 0})
196
iex> TermUI.Color.Converter.rgb_to_256({128, 128, 128})
244 # grayscale
iex> TermUI.Color.Converter.rgb_to_256({0, 255, 0})
46