Crate palette

Source
Expand description

A library that makes linear color calculations and conversion easy and accessible for anyone. It uses the type system to enforce correctness and to avoid mistakes, such as mixing incompatible color types.

§Where Do I Start?

The sections below give an overview of how the types in this library work, including color conversion. If you want to get your hands dirty, you’ll probably want to start with Srgb or Srgba. They are aliases for the more generic Rgb type and represent sRGB(A), the most common RGB format in images and tools. Their documentation has more details and examples.

The documentation for each module and type goes deeper into their concepts. Here are a few you may want to read:

  • Rgb - For getting started with RGB values.
  • Alpha - For more details on transparency.
  • convert - Describes the conversion traits and how to use and implement them.
  • cast - Describes how to cast color types to and from other data formats, such as arrays and unsigned integers.
  • color_difference - Describes different ways of measuring the difference between colors.

§Type Safety for Colors

Digital colors are not “just RGB”, and not even RGB is “just RGB”. There are multiple representations of color, with a variety of pros and cons, and multiple standards for how to encode and decode them. Palette represents these “color spaces” as separate types for increased expressiveness and to prevent mistakes.

Taking RGB as an example, it’s often stored or displayed as “gamma corrected” values, meaning that a non-linear function has been applied to its values. This encoding is not suitable for all kinds of calculations (such as rescaling) and will give visibly incorrect results. Functions that require linear RGB can therefore request, for example, LinSrgb as their input type.

// Srgb is an alias for Rgb<Srgb, T>, which is what most pictures store.
// LinSrgb is an alias for Rgb<Linear<Srgb>, T>, better for color manipulation.
use palette::{Srgb, LinSrgb};

fn do_something(a: LinSrgb, b: LinSrgb) -> LinSrgb {
// ...
}

let orangeish = Srgb::new(1.0, 0.6, 0.0);
let blueish = Srgb::new(0.0, 0.2, 1.0);
let result = do_something(orangeish, blueish); // Does not compile

The colors will have to be decoded before being used in the function:

// Srgb is an alias for Rgb<Srgb, T>, which is what most pictures store.
// LinSrgb is an alias for Rgb<Linear<Srgb>, T>, better for color manipulation.
use palette::{Srgb, LinSrgb};

fn do_something(a: LinSrgb, b: LinSrgb) -> LinSrgb {
// ...
}

let orangeish = Srgb::new(1.0, 0.6, 0.0).into_linear();
let blueish = Srgb::new(0.0, 0.2, 1.0).into_linear();
let result = do_something(orangeish, blueish);

See the rgb module for a deeper dive into RGB and (non-)linearity.

§Color Spaces and Conversion

As the previous section mentions, there are many different ways of representing colors. These “color spaces” are represented as different types in Palette, each with a description of what it is and how it works. Most of them also have two type parameters for customization:

  • The component type (T) that decides which number type is used. The default is f32, but u8, f64, and any other type that implement the required traits will work. Including SIMD types in many cases.
  • The reference white point (W) or standard (S) that affects the range, encoding or display properties of the color. This varies between color spaces and can usually be left as its default or be set via a type alias. For example, the Srgb and LinSrgb type aliases are both variants of the Rgb type, but with different standard (S) types.

Selecting the proper color space can have a big impact on how the resulting image looks (as illustrated by some of the programs in examples), and Palette makes the conversion between them as easy as a call to from_color or into_color.

This example takes an sRGB color, converts it to CIE L*C*h°, a color space similar to the colloquial HSL/HSV color spaces, shifts its hue by 180° and converts it back to RGB:

use palette::{FromColor, ShiftHue, IntoColor, Lch, Srgb};

let lch_color: Lch = Srgb::new(0.8, 0.2, 0.1).into_color();
let new_color = Srgb::from_color(lch_color.shift_hue(180.0));

§Transparency

There are many cases where pixel transparency is important, but there are also many cases where it would just be unused memory space. Palette has therefore adopted a structure where the transparency component (alpha) is attachable using the Alpha type. This approach has shown to be very modular and easy to maintain, compared to having transparent copies of each type.

An additional benefit is allowing operations to selectively affect the alpha component:

// Each color type has a transparent alias that ends with "a" for "alpha"
use palette::{LinSrgb, LinSrgba};

let mut c1 = LinSrgba::new(1.0, 0.5, 0.5, 0.8);
let c2 = LinSrgb::new(0.5, 1.0, 1.0);

c1.color = c1.color * c2; //Leave the alpha as it is
c1.blue += 0.2; //The color components can easily be accessed
c1 = c1 * 0.5; //Scale both the color and the alpha

There’s also PreAlpha that represents pre-multiplied alpha (also known as alpha masked colors). It’s commonly used in color blending and composition.

§Images and Buffers

Oftentimes, pixel data is stored in a plain array or slice such as a [u8; 3]. The cast module allows for easy conversion between Palette colors and arrays or slices. This also helps when working with other crates or systems. Here’s an example of how the pixels in an image from the image crate can be worked with as Srgb<u8>:

use image::RgbImage;
use palette::{Srgb, Oklab, cast::FromComponents, Lighten, IntoColor, FromColor};

fn lighten(image: &mut RgbImage, amount: f32) {
    // RgbImage can be dereferenced as [u8], allowing us to cast it as a
    // component slice to sRGB with u8 components.
    for pixel in <&mut [Srgb<u8>]>::from_components(&mut **image) {
        // Converting to linear sRGB with f32 components, and then to Oklab.
        let color: Oklab = pixel.into_linear::<f32>().into_color();

        let lightened_color = color.lighten(amount);

        // Converting back to non-linear sRGB with u8 components.
        *pixel = Srgb::from_linear(lightened_color.into_color());
    }
}

Some of the conversions are also implemented on the color types as From, TryFrom, Into, TryFrom and AsRef. This example shows how from can be used to convert a [u8;3] into a Palette color, into_format converts from Srgb<u8> to Srgb<f32>, and finally into converts back from a Palette color back to a [u8;3]:

use approx::assert_relative_eq;
use palette::Srgb;

let buffer = [255, 0, 255];
let srgb = Srgb::from(buffer);
assert_eq!(srgb, Srgb::<u8>::new(255u8, 0, 255));

let srgb_float: Srgb<f32> = srgb.into_format();
assert_relative_eq!(srgb_float, Srgb::new(1.0, 0.0, 1.0));

let array: [u8; 3] = srgb_float.into_format().into();
assert_eq!(array, buffer);

§A Basic Workflow

The overall workflow can be divided into three steps, where the first and last may be taken care of by other parts of the application:

Decoding -> Processing -> Encoding

§1. Decoding

Find out what the source format is and convert it to a linear color space. There may be a specification, such as when working with SVG or CSS.

When working with RGB or gray scale (luma):

  • If you are asking your user to enter an RGB value, you are in a gray zone where it depends on the context. It’s usually safe to assume sRGB, but sometimes it’s already linear.

  • If you are decoding an image, there may be some meta data that gives you the necessary details. Otherwise it’s most commonly sRGB. Usually you will end up with a slice or vector with RGB bytes, which can easily be converted to Palette colors:

use palette::{Srgb, cast::ComponentsAsMut};

// This works for any color type (not only RGB) that can have the
// buffer element type as component.
let color_buffer: &mut [Srgb<u8>] = image_buffer.components_as_mut();
  • If you are getting your colors from the GPU, in a game or other graphical application, or if they are otherwise generated by the application, then chances are that they are already linear. Still, make sure to check that they are not being encoded somewhere.

When working with other colors:

  • For HSL, HSV, HWB: Check if they are based on any other color space than sRGB, such as Adobe or Apple RGB.

  • For any of the CIE color spaces, check for a specification of white point and light source. These are necessary for converting to RGB and other colors, that depend on perception and “viewing devices”. Common defaults are the D65 light source and the sRGB white point. The Palette defaults should take you far.

§2. Processing

When your color has been decoded into some Palette type, it’s ready for processing. This includes things like blending, hue shifting, darkening and conversion to other formats. Just make sure that your non-linear RGB is made linear first (my_srgb.into_linear()), to make the operations available.

Different color spaced have different capabilities, pros and cons. You may have to experiment a bit (or look at the example programs) to find out what gives the desired result.

§3. Encoding

When the desired processing is done, it’s time to encode the colors back into some image format. The same rules applies as for the decoding, but the process reversed.

Re-exports§

pub use color_difference::ColorDifference;Deprecated
pub use convert::FromColor;
pub use convert::FromColorMut;
pub use convert::FromColorMutGuard;
pub use convert::IntoColor;
pub use convert::IntoColorMut;

Modules§

alpha
Types related to transparent colors.
angle
Traits for working with angular values, such as for in hues.
blend
Color blending and blending equations.
bool_mask
Traits for abstracting over Boolean types.
cam16
Types for the CIE CAM16 color appearance model.
cast
Traits and functions for casting colors to and from other data types.
chromatic_adaptation
Convert colors from one reference white point to another
color_difference
Algorithms for calculating the difference between colors.
color_theory
Traits related to traditional color theory.
convert
Traits for converting between color spaces.
encoding
Number and color encoding traits, types and standards.
hsl
Types for the HSL color space.
hsluv
Types for the HSLuv color space.
hsv
Types for the HSV color space.
hues
Hues and hue related types.
hwb
Types for the HWB color space.
lab
Types for the CIE L*a*b* (CIELAB) color space.
lch
Types for the CIE L*C*h° color space.
lchuv
Types for the CIE L*C*uv h°uv color space.
luma
Types for luma and luminance (grayscale) values.
luv
Types for the CIE L*u*v* (CIELUV) color space.
named
A collection of named color constants. Can be toggled with the "named" and "named_from_str" Cargo features.
num
Traits for abstracting over numeric types.
okhsl
Types for the Okhsl color space.
okhsv
Types for the Okhsv color space.
okhwb
Types for the Okhwb color space.
oklab
Types for the Oklab color space.
oklch
Types for the Oklch color space.
rgb
Types for the RGB color space, including spaces and standards.
serde
Utilities for serializing and deserializing with serde.
stimulus
Traits for working with stimulus colors and values, such as RGB and XYZ.
white_point
Defines the tristimulus values of the CIE Illuminants.
xyz
Types for the CIE 1931 XYZ color space.
yxy
Types for the CIE 1931 Yxy (xyY) color space.

Structs§

Alpha
An alpha component wrapper for colors, for adding transparency.
Hsl
HSL color space.
Hsluv
HSLuv color space.
Hsv
HSV color space.
Hwb
HWB color space.
Lab
The CIE L*a*b* (CIELAB) color space.
LabHue
A hue type for the CIE L*a*b* family of color spaces.
Lch
CIE L*C*h°, a polar version of CIE L*a*b*.
Lchuv
CIE L*C*uv h°uv, a polar version of CIE L*u*v*.
Luv
The CIE L*u*v* (CIELUV) color space.
LuvHue
A hue type for the CIE L*u*v* family of color spaces.
Okhsl
A Hue/Saturation/Lightness representation of Oklab in the sRGB color space.
Okhsv
A Hue/Saturation/Value representation of Oklab in the sRGB color space.
Okhwb
A Hue/Whiteness/Blackness representation of Oklab in the sRGB color space, similar to Hwb.
Oklab
The Oklab color space.
OklabHue
A hue type for the Oklab color space.
Oklch
Oklch, a polar version of Oklab.
RgbHue
A hue type for the RGB family of color spaces.
Xyz
The CIE 1931 XYZ color space.
Yxy
The CIE 1931 Yxy (xyY) color space.

Traits§

ArrayExt
Extension trait for fixed size arrays.
Clamp
An operator for restricting a color’s components to their expected ranges.
ClampAssign
An assigning operator for restricting a color’s components to their expected ranges.
Darken
Operators for darkening a color;
DarkenAssign
Assigning operators for darkening a color;
Desaturate
Operator for decreasing the saturation (or chroma) of a color.
DesaturateAssign
Assigning operator for decreasing the saturation (or chroma) of a color.
GetHue
A trait for colors where a hue may be calculated.
IsWithinBounds
Checks if color components are within their expected range bounds.
Lighten
Operators for lightening a color.
LightenAssign
Assigning operators for lightening a color.
Mix
Linear color interpolation of two colors.
MixAssign
Assigning linear color interpolation of two colors.
NextArray
Temporary helper trait for getting an array type of size N + 1.
RelativeContrastDeprecated
A trait for calculating relative contrast between two colors.
Saturate
Operator for increasing the saturation (or chroma) of a color.
SaturateAssign
Assigning operator for increasing the saturation (or chroma) of a color.
SetHue
Change the hue of a color to a specific value without moving.
ShiftHue
Operator for increasing or decreasing the hue by an amount.
ShiftHueAssign
Assigning operator for increasing or decreasing the hue by an amount.
WithAlpha
A trait for color types that can have or be given transparency (alpha channel).
WithHue
Change the hue of a color to a specific value.

Functions§

contrast_ratioDeprecated
Calculate the ratio between two luma values.

Type Aliases§

GammaLuma
Gamma 2.2 encoded luminance.
GammaLumaa
Gamma 2.2 encoded luminance with an alpha component.
GammaSrgb
Gamma 2.2 encoded sRGB.
GammaSrgba
Gamma 2.2 encoded sRGB with an alpha component.
Hsla
Linear HSL with an alpha component. See the Hsla implementation in Alpha.
Hsluva
HSLuv with an alpha component. See the Hsluva implementation in Alpha.
Hsva
Linear HSV with an alpha component. See the Hsva implementation in Alpha.
Hwba
Linear HWB with an alpha component. See the Hwba implementation in Alpha.
Laba
CIE L*a*b* (CIELAB) with an alpha component. See the Laba implementation in Alpha.
Lcha
CIE L*C*h° with an alpha component. See the Lcha implementation in Alpha.
Lchuva
CIE L*C*uv h°uv with an alpha component. See the Lchuva implementation in Alpha.
LinLuma
Linear luminance.
LinLumaa
Linear luminance with an alpha component.
LinSrgb
Linear sRGB.
LinSrgba
Linear sRGB with an alpha component.
Luva
CIE L*u*v* (CIELUV) with an alpha component. See the Luva implementation in Alpha.
Mat3
A 9 element array representing a 3x3 matrix.
Okhsla
Okhsl with an alpha component.
Okhsva
Okhsv with an alpha component. See the Okhsva implementation in Alpha.
Okhwba
Okhwb with an alpha component. See the Okhwba implementation in Alpha.
Oklaba
Oklab with an alpha component.
Oklcha
Oklch with an alpha component. See the Oklcha implementation in Alpha.
Srgb
Non-linear sRGB, the most common RGB input/output format.
SrgbLuma
sRGB encoded luminance.
SrgbLumaa
sRGB encoded luminance with an alpha component.
Srgba
Non-linear sRGB with an alpha component.
Xyza
CIE 1931 XYZ with an alpha component. See the Xyza implementation in Alpha.
Yxya
CIE 1931 Yxy (xyY) with an alpha component. See the Yxya implementation in Alpha.

Derive Macros§

WithAlpha