[ANN] colors 0.0.1 – colorspace manipulation in pure OCaml

Hi folks :wave: just wanted to share a little library I put together to do color manipulation in Mint Tea. It’ll be used in the next release of Mint Tea, and allow us to do gradients and all sorts of nice color stuff:



This first release of colors:

  • Introduces RGB, LRGB, XYZ, LUV, UV types
  • Includes standard white reference point d65
  • Supports Linearizing/Delinearizing RGB
  • Includes conversions between ANSI, RGB, LRGB, XYZ, and LUV
  • Has blending for LUV and RGB (via LUV) with configurable mixing
  • Includes an ANSI to RGB color table

I’m hoping to keep it super small and in pure OCaml so we can use it for terminals but also other places like web, or other graphics settings.

You can read the full changelog here.

If you’re interested in contributing to any of these, look for open good first issues, and don’t hesitate to reach out on Discord/X: @leostera :slight_smile:

Happy hacking! :camel: :hand_with_index_finger_and_thumb_crossed:


Great work. Color is harder than a lot of folks think.


Just out of pure curiosity, why is it implemented using polymorphic variants rather than plain variants?

Not OP, but with polymorphic variants you can define colors in a library without depending on the colors library.

But shouldn’t one depend on colors to use its functionality?

The main reasons are:

  • usability – its trivial for folks to put tag triples with their color profile – if you have 3 floats you can pack 'em up and say “this is an `rgb or an `xyz color”.

  • flexibility – some functions can work over multiple types of colors, say a generic mixer/blender can just say its input type is [ rgb | xyz ] -> xyz.

    Other functions like the pretty printer can take in all colors so their type is [ rgb | lrgb | xyz | luv | ansi ]

  • extensibility – if you’re currently handling any colors, we can still add new profiles without breaking your code.

We could’ve used a record too for each type: {r;g;b}, {x;y;z}, {sr;sg;sb}, etc, but the tuple of int/float felt the most ergonomic.

I’m a big fan of the maximum type-safety that will not get in the way of DX.