A Rust library that makes linear color calculations and conversion easy and accessible for anyone. It provides both precision tools that lets you work in exactly the color space you want to, as well as a general color type that abstracts away some of the technical details.
Add the following lines to your Cargo.toml
file:
[dependencies]
palette = "0.5"
These features are enabled by default:
"named"
- Enables color constants, located in thenamed
module."named_from_str"
- Enables thenamed::from_str
, which maps name string to colors. This requires the standard library."std"
- Enables use of the standard library.
These features are disabled by default:
"serializing"
- Enables color serializing and deserializing usingserde
."libm"
- Makes it use thelibm
floating point math library. It's only for when the"std"
feature is disabled.
Here is an example Cargo.toml
entry for using palette on #![no_std]
:
[dependencies.palette]
version = "0.4"
default-features = false
features = ["libm"] # Makes it use libm instead of std for float math
Colors in, for example, images are often "gamma corrected" or stored in sRGB format as a compression method and to prevent banding. This is also a bit of a legacy from the ages of the CRT monitors, where the output from the electron gun was nonlinear. The problem is that these formats don't represent the actual intensities, and the compression has to be reverted to make sure that any operations on the colors are accurate. This library uses a completely linear work flow, and comes with the tools for transitioning between linear and non-linear RGB.
Adding to that, there are more than one kind of non-linear RGB. Ironically enough, this turns RGB into one of the most complex color spaces.
Palette provides tools for both color manipulation and conversion between color spaces. These are some highlights.
RGB is probably the most widely known color space, but it's not the only one. You have probably used a color picker with a rainbow wheel and a brightness slider. That may have been an HSV or an HSL color picker, where the color is encoded as hue, saturation and brightness/lightness. There's also a group of color spaces that are designed to be perceptually uniform, meaning that the perceptual change is equal to the numerical change.
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°, shifts its hue by 180° and converts it back to RGB:
use palette::{FromColor, Hue, 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));
This results in the following two colors:
Palette comes with a number of color manipulation tools, that are implemented as traits. These includes lighten/darken, saturate/desaturate and hue shift. These traits are only implemented on types where they are meaningful, which means that you can't shift the hue of an RGB color without converting it to a color space where it makes sense.
The following example shows how to make a lighter and a desaturated version of the original.
use palette::{FromColor, Saturate, Shade, Srgb, Lch};
let color = Srgb::new(0.8, 0.2, 0.1).into_linear();
let lighter = color.lighten(0.1);
let desaturated = Lch::from_color(color).desaturate(0.5);
This results in the following three colors:
There is also a linear gradient type which makes it easy to interpolate between a series of colors. This gradient can be used in any color space and it can be used to make color sequence iterators.
The following example shows three gradients between the same two endpoints, but the top is in RGB space while the middle and bottom are in HSV space. The bottom gradient is an example of using the color sequence iterator.
use palette::{FromColor, LinSrgb, Hsv, Gradient};
let grad1 = Gradient::new(vec![
LinSrgb::new(1.0, 0.1, 0.1),
LinSrgb::new(0.1, 1.0, 1.0)
]);
let grad2 = Gradient::new(vec![
Hsv::from_color(LinSrgb::new(1.0, 0.1, 0.1)),
Hsv::from_color(LinSrgb::new(0.1, 1.0, 1.0))
]);
The RGB gradient goes through gray, while the HSV gradients only change hue:
Palette supports converting from a raw buffer of data into a color type using the Pixel
trait. This is useful for interoperation with other crates or programs.
Oftentimes, pixel data is stored in a raw buffer such as a [u8; 3]
. from_raw
can be used to convert into a Palette color, into_format
converts from Srgb<u8>
to Srgb<f32>
, and finally into_raw
to convert from a Palette color back to a [u8;3]
.
Here's an example of turning a buffer of [u8; 3]
into a Palette Srgb
color and back to a raw buffer.
use approx::assert_relative_eq;
use palette::{Srgb, Pixel};
let buffer = [255, 0, 255];
let raw = Srgb::from_raw(&buffer);
assert_eq!(raw, &Srgb::<u8>::new(255u8, 0, 255));
let raw_float: Srgb<f32> = raw.into_format();
assert_relative_eq!(raw_float, Srgb::new(1.0, 0.0, 1.0));
let raw: [u8; 3] = Srgb::into_raw(raw_float.into_format());
assert_eq!(raw, buffer);
This library is only meant for color manipulation and conversion. It's not a fully featured image manipulation library. It will only handle colors, and not whole images. There are features that are meant to work as bridges between Palette and other graphical libraries, but the main features are limited to only focus on single pixel operations, to keep the scope at a manageable size.
Palette supports #![no_std]
environments by disabling the "std"
feature. However, there are some things that are unavailable without the standard library:
- Gradients are unavailable, because they depend heavily on Vectors
- The
"named_from_str"
feature requires the standard library as well - Serialization using
serde
is unavailable
It uses libm
to provide the floating-point operations that are typically in std
.
All sorts of contributions are welcome, no matter how huge or tiny, so take a look at CONTRIBUTING.md for guidelines, if you are interested.
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.