TermUI.Color.Converter (TermUI v1.0.0)

View Source

Color 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

ModeColorsUse Case
:true_color16.7MModern terminals (24-bit RGB)
:color_256256Most Unix terminals
:color_1616Basic terminal compatibility
:monochrome2Minimal 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

grayscale?(arg)

@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

luminance_weights()

@spec luminance_weights() :: {float(), float(), float()}

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

rgb_to_16(arg, atom)

@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-255
  • type - :fg for foreground or :bg for 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)

rgb_to_256(rgb)

@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