2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00
2026-07-14 13:00:12 -04:00

color

24-bit RGB values, perceptual metrics, and blend operations. No output device, no dependencies.

Extracted from lixenwraith/terminal so renderers — terminal, GUI, image, framebuffer — share one color type and one set of operations without linking terminal I/O, x/sys, or termios.

Install

go get github.com/lixenwraith/color

Go 1.26+. Standard library only.

Type

type RGB struct {
    R uint8 `toml:"r"`
    G uint8 `toml:"g"`
    B uint8 `toml:"b"`
}

Three bytes, comparable, pointer-free: safe to embed in dense cell or pixel buffers and to bind directly from config.

RGB implements image/color.Color, so values pass into image, draw, and GUI toolkit pipelines unchanged. From converts back, un-premultiplying alpha and discarding it.

img.Set(x, y, color.Amber)          // RGB satisfies image/color.Color
c := color.From(img.At(x, y))       // back to RGB

Where both packages are needed at one site, alias the standard library: import stdcolor "image/color".

Operations

Call Behavior
Blend(dst, src, alpha) Linear alpha compositing
SoftLight(dst, src, intensity) Perez soft light; gentler than linear alpha
Overlay(dst, src, alpha) Multiply on darks, screen on lights
Screen(dst, src, alpha) Always lightens; glow accumulation without Add clipping
Add(dst, src, alpha) Saturating additive
Max(dst, src, alpha) Per-channel maximum
Scale(c, factor) Channel multiply, saturating
Grayscale(c), Luma(c) Rec. 601 luma
c.Lerp(other, t) Linear interpolation
RedmeanDistance(a, b) Squared perceptual distance, for nearest-color search

All operations are pure. alpha and t clamp to [0,1]; channels saturate. Integer paths avoid division; soft light is table-driven, no sqrt per channel.

bg   := color.Obsidian
glow := color.Screen(bg, color.Amber, 0.4)
edge := bg.Lerp(color.Amber, 0.75)
warm := color.SoftLight(edge, color.Terracotta, 0.3)

Palette

~120 named colors, grouped by hue and ordered dark-to-light: Obsidian, Amber, EmeraldGreen, LightSkyBlue, Vermilion, … Standard names (CSS, X11) where the RGB matches; descriptive compounds otherwise.

Package-level vars. Read-only by contract — the language permits assignment, the package does not. Alias them into domain parameter files rather than mutating them.

Hex

c, err := color.ParseHex("#4a90d9")     // also "4a90d9", "#abc", "abc"
s := c.Hex()                            // "#4a90d9"
var Accent = color.MustParseHex("#ff8800")

RGB deliberately does not implement encoding.TextUnmarshaler. TOML and JSON decoders prefer it over struct-field unification, which would silently break table-form config:

accent = { r = 255, g = 136, b = 0 }

With terminal

terminal.Cell carries color.RGB directly. Quantization stays device-side:

idx := terminal.RGBTo256(color.EmeraldGreen)   // xterm-256 index

Note: when Cell.Attrs sets AttrFg256 / AttrBg256, Cell.Fg.R / Cell.Bg.R hold a palette index, not a channel. Such values are not colors and must not be passed to this package.

Concurrency

Values are immutable, operations are pure, lookup tables are built at package init. Safe for concurrent use.

License

See LICENSE.

S
Description
No description provided
Readme BSD-3-Clause
54 KiB
Languages
Go 100%