Skip to main content

Concepts

Value ranges and clamping

Each component has a defined valid range. With the exception of hex strings, values outside the range are clamped on assignment using the clamp() function from renfordt/clamp. No exception is raised for out-of-range numeric input.

ComponentRangeType
RGB red / green / blue0–255int
RGB alpha0–255int
Hue (HSL, HSV)0–360int
Saturation (HSL, HSV)0.0–1.0float
Lightness (HSL)0.0–1.0float
Value (HSV)0.0–1.0float
Alpha (HSL, HSV)0.0–1.0float

Example:

$rgb = RGBColor::create([255, 100, 50]);
$rgb->green = 300; // stored as 255
$rgb->blue = -10; // stored as 0

Hex strings are validated instead of clamped. A string that is not 3, 4, 6, or 8 hexadecimal digits (ignoring an optional leading #) raises InvalidArgumentException. See HexColor.

Alpha channel

HexColor, RGBColor, HSLColor, and HSVColor carry an optional alpha (opacity) channel. Alpha is optional everywhere and defaults to fully opaque, so existing code that never mentions alpha keeps producing fully opaque colors.

The channel is represented differently per format, matching each format's native convention:

FormatAlpha representation
RGBColorint 0255 (255 = opaque), as a 4th element/property
HexColora 4th/8th hex digit pair (#RRGGBBAA / #RGBA)
HSLColorfloat 0.01.0 (1.0 = opaque), as a 4th element
HSVColorfloat 0.01.0 (1.0 = opaque), as a 4th element
// Half-transparent red, expressed in each format
$rgb = RGBColor::create([255, 0, 0, 128]);
$hex = HexColor::create('#FF000080');
$hsl = HSLColor::create([0, 1.0, 0.5, 0.5]);
$hsv = HSVColor::create([0, 1.0, 1.0, 0.5]);

Alpha is preserved through conversions. Converting an RGBA color to HSL, HSV, or hex keeps the opacity, translating between the int (0255) and float (0.01.0) representations as needed.

RGBColor::create([255, 0, 0, 128])->toHex()->getHexStr(); // #ff000080
HexColor::create('#FF000080')->toHSL()->alpha; // ~0.502

HexColor normalizes a fully opaque alpha away, so opaque colors are always rendered in their plain 3-/6-digit form (#FF0000FF becomes #FF0000). Use getAlpha() to read the alpha of a HexColor as an int 0255.

RALColor and NamedColor have no alpha channel; convert them to one of the formats above first if you need to apply opacity.

Standard color names

NamedColor represents the standard set of CSS/X11 color names (e.g. red, rebeccapurple, dodgerblue). Names are stored normalized (trimmed and lower-cased) and validated against the known list, so an unknown name raises InvalidArgumentException. A single name→hex table is the source of truth; every other representation is derived through the normal conversion chain.

NamedColor can also work in reverse: find the exact name for a color (fromHex() / fromRGB()) or the nearest name when there is no exact match (findClosest()). RGBColor::getName() and HexColor::getName() are convenience wrappers around the exact lookup. See NamedColor.

Conversion routing

Most conversions are not implemented directly between every pair of formats. Instead they route through intermediate formats:

  • Hex and RGB convert directly to each other using bitwise operations.
  • HSL and HSV convert to and from RGB. Their hex conversions go through RGB.
  • RGB to HSL/HSV is computed from chroma, value, and hue, derived in the private calculateCVH() method of RGBColor.
  • RAL converts to hex via its lookup table, then to any other format through hex.
  • Named colors convert to hex via their lookup table, then to any other format through hex.

This means a conversion such as HSL to HSV is performed as HSL → RGB → HSV.

Precision

Conversions that produce HSL or HSV from RGB or hex accept an optional $precision argument (default 4). It controls the number of decimal places the saturation and lightness/value results are rounded to. The hue is always rounded to the nearest integer.

$hsl = $rgb->toHSL(precision: 2);

RALColor::toHSL() and RALColor::toHSV() do not expose a precision parameter and use the default.

Property hooks

The color classes use PHP 8.4 property hooks to expose components as public properties while still enforcing validation. Reading a property returns the stored value; assigning one runs the clamp (or, for hex, the format check) before storing. This is why a plain property assignment such as $rgb->green = 300 results in a clamped value rather than an invalid one.