Crate colstodian

source ·
Expand description

An opinionated color management library for games and graphics.

Introduction

Color is a really complex and fascinating topic, and I’d love to take you on a little tour and show you how colstodian tries to help make it easier to manage. But, if you really just want to get sh*t done right now, here’s the basics:

Color is a unified type representing a color in any ColorEncoding. The ColorEncoding defines a bunch of different properties about how the color values are stored and what those values actually mean. For example, Color<SrgbU8> is a color with red, green, and blue values that vary from 0-255 and the meaning of those values is defined by the full sRGB color encoding standard. The most common and standard color encodings are exposed in the basic_encodings module.

Many built-in color encodings expose constructor functions on the Color type. See the docs for that type for a full list. The ones you are likely most interested in if you don’t know much about color are:

  • Color::srgb_u8: If you have three 0-255 values, this is what you want
  • Color::srgb_f32: If you have three 0.0..=1.0 values, this is probably what you want
  • Color::linear_srgb: If you have three 0.0..=1.0 values that you know are “linear rgb”, this is probably what you want

If you also have alpha (i.e. four values instead of three), then Color::srgba_u8, Color::srgba_f32, and Color::linear_srgba are the equivalents of the above with an alpha component.

If you want to do math to a color (for example, adding two colors together or multiplying one by a coefficient), you’ll want to do so in a color encoding that is conducive to that. Color encodings which have this property implement the WorkingEncoding trait. If a Color is not encoded in a working encoding, it will not implement common math traits like addition, multiplication, etc.

The most common WorkingEncoding is LinearSrgb. You can convert a color you have created using any of the constructors above to LinearSrgb by using the .convert::<E>() method.

If you want to output a color into an image file, the most common color encoding for most common image formats (and the one assumed by viewing programs if a color profile is not embedded) is SrgbU8. You can convert a color from a working encoding to SrgbU8 for output again with the .convert::<E>() method.

Example

Here we construct two colors in different ways, convert them both to LinearSrgb to work with them, and then convert the result to SrgbU8 which can be passed on to be displayed in an image.

use colstodian::Color;
use colstodian::basic_encodings::{SrgbU8, LinearSrgb};

let color1 = Color::srgb_u8(102, 54, 220);
let color2 = Color::srgb_f32(0.5, 0.8, 0.1);

let color1_working = color1.convert::<LinearSrgb>();
let color2_working = color2.convert::<LinearSrgb>();

let result_working = color1_working * 0.5 + color2_working;

let output = result_working.convert::<SrgbU8>();

assert_eq!(output, Color::srgb_u8(144, 206, 163));

Color Encoding Basics

Much like how a 3d vector like a glam::Vec3 could be used to describe any of:

  • The motion vector of an object in meters per second
  • The position of an object relative to a reference point in kilometers
  • Three “wellness scores” for a character, which each axis representing how happy the character is about some aspect of their life

A bag of components that describes “a color” could actually be interpreted in many different ways, and the end result of what those components mean is very different.

colstodian gathers all the information that defines how a color is represented in data as well as what that data actually means into representative types that implement the ColorEncoding trait.

Modules

Macros

  • Assert that $left and $right are equal within a margin of $eps.

Structs

Traits

  • A type that implements ColorEncoding represents a collection of metadata that together defines how a color’s data is stored and what the values of that data actually mean.
  • Like Into but specialized for use with colstodian Color types.
  • Implemented by color encodings which are designed to be perceptually-uniform. In general these encodings will produce more visually pleasing results when blending between colors (for example, creating gradients) in many situations. However they are certainly not, silver bullets, and often don’t fully deliver on the promise of perceptual uniformity.
  • Marks a type as representing a color encoding in which it makes sense to be able to perform mathematical operations on the contained color values directly.