It has now been nearly three weeks since version 0.1.0 of Palette, a linear color calculation and conversion library for Rust, was released, but it has already gone through some big and important changes, so I thought it would be a good idea to describe them in a bit more detail. Let’s take a look at what’s new.

## Slicing Gradients

Palette provides a `Gradient`

type for linear color interpolation. The basic
idea is that you can define a series of control points (colors mapped to
numbers), and the `Gradient`

will mix them to give you any color between them.
The colors beyond the endpoints of the series will be the same as at the
nearest endpoint.

The new slicing feature lets you create an other gradient, which is based on the original one, but with a different domain (or range). Everything outside this new domain will have the same color as at the nearest of its endpoints, so it’s the same behavior as before, but with new endpoints. Let’s take a look at an example:

```
//Create a gradient from red to blue. The default domain is 0.0 to 1.0.
let g1 = Gradient::new(vec![Rgb::new(1.0, 0.0, 0.0), Rgb::new(0.0, 0.0, 1.0)]);
//Slice it to only include the first half.
let g2 = g1.slice(..0.5);
assert_eq!(g1.get(0.0), g2.get(0.0)); //Ok
assert_eq!(g1.get(0.3), g2.get(0.3)); //Ok
assert_eq!(g1.get(0.5), g2.get(0.5)); //Ok
assert_eq!(g1.get(0.7), g2.get(0.7)); //Error!
```

The reason for the error is that `0.7`

is outside the domain of `g2`

, so it
gives `RGB(0.5, 0.0, 0.5)`

(the color at `0.5`

) instead of `RGB(0.3, 0.0, 0.7)`

.

See the documentation for more info about `Gradient`

.

## Color Arithmetics

One of the two main purposes of Palette is doing maths with colors and that
has now been made a lot simpler. The basic arithmetic operations (`+`

, `-`

,
`*`

and `/`

) has been implemented for each color space, and allows both
another color and a plain number as the right hand side.

```
let a = Rgb::new(1.0, 0.5, 0.3);
let b = Rgb::new(0.1, 0.5, 0.2);
//It's now possible to do this:
let c = a * b;
//...instead of this:
let c = Rgb::new(a.red * b.red, a.green * b.green, a.blue * b.blue);
//...and this:
let c = a * 0.5;
//...instead of this:
let c = Rgb::new(a.red * 0.5, a.green * 0.5, a.blue * 0.5);
```

The only exceptions are the hue based colors (HSV, HSL, etc.), since multiplication and division of the hue isn’t well defined. They do still implement addition and subtraction, so they are not completely left outside.

## Working With Any Float

The colors were initially represented by `f32`

components, which may be too
limited for some high precision applications, so every single color type was
rewritten to be based on any `T: num::Float`

. The difference isn’t directly
apparent, since the default is still `f32`

, but it’s now possible to use
`Rgb<f64>`

or even `Rgb<MyIncreatibelFloatType>`

.

The operation traits, like `Mix`

and `Shade`

, has been given an associated
type, called `Scalar`

. This corresponds to the type parameter `T`

in the color
spaces and allows some simplification when they are used together, like in
`Gradient<C: Mix + Clone>`

.

## Separating Transparency From Color

The second big change was the separation of the transparency (alpha) component
from the colors. The `alpha`

was initially a mandatory part of each color, but
this came with increased memory usage if many colors are to be stored, so some
kind of decoupling was necessary.

One idea was to make duplicates of each color type, where one has the `alpha`

component and the other doesn’t. This is simple and can easily be automated.
The other idea was to make more use of the type system and create a
transparent wrapper type which would carry the `alpha`

component. This ended
up being the final solution and comes with some interesting possibilities.

The new system introduces an `Alpha<C, T: Float>`

type, which is defined as

```
pub struct Alpha<C, T: Float> {
color: C,
alpha: T,
}
```

This type implements all of the operation traits, as well as `Deref`

and
`DerefMut`

to also expose the content of `color`

. This allows operations on
`color`

+ `alpha`

as a whole, as well as isolated operations on just `color`

without any conversion. Take a look at this example from the documentation:

```
use palette::{Rgb, Rgba};
let mut c1 = Rgba::new(1.0, 0.5, 0.5, 0.8);
let c2 = Rgb::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
```

The `Rgba`

type is an alias for `Alpha<Rgb<T>, T>`

and it implements the
necessary functions for it to behave in the same way as `Rgb`

. There are also
aliases for the other color spaces.

You can read a bit more about `Alpha`

in the documentation.

## Separation of Pixel Encodings

An other important change is the separation of sRGB and gamma correction
related things from the `Rgb`

type. The distinction between linear and non-
linear colors is now encoded into the type system as the `Srgb`

and `GammaRgb`

types. They are meant as transition types when converting from a linear color
to some kind of pixel representation, and back. This change has also resulted
in a `pixel`

module, where all the pixel format related types can be found.

See the documentation for more.

## New Constructor Names

Last, but not least, is a short PSA regarding the new constructor names. The
separation of transparency, and the new RGB types made the old constructor
naming convention (like `Rgb::rgb(...)`

) unnecessary. Each type (`Rgb`

,
`Rgba`

, `Srgb`

, etc.) can now be constructed with a `new`

function, and
sometimes with an additional `new_u8`

function. The `Color`

type is mostly as
before, though, with the exception of the transparency variants.

## What’s Next?

The next phase will focus on adding some new features. There are already some to-do issues that has been scheduled for version 0.2.1, including named colors, blending and the addition of xyY support. A further goal is to implement variable white points and chromatic adaption.

Palette can be found on GitHub, where contributions are most welcome, and on crates.io.

Thank you for reading this, and have fun making colorful creations!