abachrome

How do I convert between color spaces in Ruby?

Every Abachrome color object exposes to_srgb, to_oklab, to_oklch, and other conversion methods. Conversions chain automatically through intermediate spaces, so you never need to manage the conversion graph yourself.

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°)

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)

Available Color Spaces

SymbolDescription
:srgbStandard RGB (web/display)
:lrgbLinear RGB (gamma-decoded)
:oklabPerceptually uniform Lab (OKLab)
:oklchCylindrical OKLab (lightness/chroma/hue)
:xyzCIE XYZ absolute color space
:lmsCone response (basis for OKLab)
:hsvHue-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)

Notes

  • Conversions go through intermediate spaces (e.g., sRGB → Linear RGB → XYZ → LMS → OKLab) but the path is resolved automatically.
  • Abachrome uses BigDecimal internally to minimise floating-point drift across multi-step conversions.