How do I convert between color spaces in Ruby?
Different color spaces serve different purposes, and we often need to move between them. sRGB is what browsers and CSS understand. OKLab and OKLCH are perceptually uniform, making them better suited for blending and lightness adjustments. Linear RGB is what rendering math expects before gamma correction applies. Abachrome lets us move between all of these without managing the conversion graph ourselves.
Every Abachrome color object exposes to_srgb, to_oklab, to_oklch, and other conversion methods. You might wonder what happens when you convert between spaces that are not directly connected — conversions chain automatically through intermediate spaces, so you get the right result regardless of which space you start from.
Direct Conversion
require 'abachrome'
color = Abachrome.from_hex('#e63946')
srgb = color.to_srgb
lab = color.to_oklab
lch = color.to_oklch
puts lch.coordinates.map { |c| c.round(4) }.inspect
# => [0.5543, 0.2018, 26.7] (lightness, chroma, hue°)
The three OKLCH coordinates — lightness, chroma, and hue — give you intuitive handles on the color’s perceptual properties. You can inspect them to understand a color, or modify them directly to adjust it.
Using the Generic Converter
Abachrome.convert accepts any color and a target space name as a symbol:
color = Abachrome.from_hex('#06d6a0')
in_lch = Abachrome.convert(color, :oklch)
in_lab = Abachrome.convert(color, :oklab)
in_lrgb = Abachrome.convert(color, :lrgb)
This is useful when the target space is determined at runtime rather than hard-coded.
Available Color Spaces
| Symbol | Description |
|---|---|
:srgb | Standard RGB (web/display) |
:lrgb | Linear RGB (gamma-decoded) |
:oklab | Perceptually uniform Lab (OKLab) |
:oklch | Cylindrical OKLab (lightness/chroma/hue) |
:xyz | CIE XYZ absolute color space |
:lms | Cone response (basis for OKLab) |
:hsv | Hue-Saturation-Value |
Registering a Custom Color Space
If your workflow uses a proprietary or nonstandard space, you can register it at startup:
Abachrome.register_color_space(:my_space) do |space|
# define axes, ranges, etc.
end
Abachrome.register_converter(:srgb, :my_space, MySpaceConverter.new)
This extensibility is worth knowing about if you work in fields like print production or broadcast, where industry-specific color spaces are common.
Notes
- Conversions go through intermediate spaces (e.g., sRGB → Linear RGB → XYZ → LMS → OKLab) but the path is resolved automatically.
- Abachrome uses
BigDecimalinternally to minimise floating-point drift across multi-step conversions.