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.
| Component | Range | Type |
|---|---|---|
| RGB red / green / blue | 0–255 | int |
| RGB alpha | 0–255 | int |
| Hue (HSL, HSV) | 0–360 | int |
| Saturation (HSL, HSV) | 0.0–1.0 | float |
| Lightness (HSL) | 0.0–1.0 | float |
| Value (HSV) | 0.0–1.0 | float |
| Alpha (HSL, HSV) | 0.0–1.0 | float |
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:
| Format | Alpha representation |
|---|---|
RGBColor | int 0–255 (255 = opaque), as a 4th element/property |
HexColor | a 4th/8th hex digit pair (#RRGGBBAA / #RGBA) |
HSLColor | float 0.0–1.0 (1.0 = opaque), as a 4th element |
HSVColor | float 0.0–1.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 (0–255) and float
(0.0–1.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 0–255.
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 ofRGBColor. - 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.