#srgb #xyz #color #rgb #rec709

srgb

sRGB primitives and constants — lightweight crate with functions and constants needed when manipulating sRGB colours

7 releases

0.2.3 Jul 1, 2021
0.2.2 Jun 8, 2021
0.2.1 May 17, 2021
0.1.4 Apr 30, 2021

#86 in Images

Download history 41/week @ 2021-04-21 26/week @ 2021-04-28 17/week @ 2021-05-05 27/week @ 2021-05-12 7/week @ 2021-05-19 7/week @ 2021-05-26 12/week @ 2021-06-02 22/week @ 2021-06-09 3/week @ 2021-06-16 10/week @ 2021-06-23 20/week @ 2021-06-30 12/week @ 2021-07-07 14/week @ 2021-07-14 6/week @ 2021-07-21

57 downloads per month
Used in 2 crates

LGPL-3.0-or-later

44KB
675 lines

sRGB primitives and constants

A lightweight crate providing functions and constants used in sRGB colour space. Specifically gamma correction, D65 definition, XYZ conversion functions and constants and Rec.709 encoding and decoding routines.

The crate intents to provide low-level primitives needed to work with sRGB colour space. Those primitives can be used by other libraries which need to convert between sRGB and other colour spaces (if the conversion requires going through XYZ colour space) or blend colours together (which requires performing gamma correction).

Usage

Using this package with Cargo projects is as simple as adding a single dependency:

[dependencies]
srgb = "0.1"

With that dependency in place, it’s now simple to write an application which converts an sRGB colour into other colour spaces:

#[derive(Debug)]
struct RGB(u8, u8, u8);

impl RGB {
    fn parse(value: &str) -> Option<Self> {
        value.strip_prefix('#')
            .and_then(|v| (v.len() == 6 && !v.starts_with('+')).then(|| v))
            .and_then(|v| u32::from_str_radix(v, 16).ok())
            .map(|v| Self((v >> 16) as u8, (v >> 8) as u8, v as u8))
    }

    fn normalise(&self) -> (f32, f32, f32) {
        let [r, g, b] = srgb::normalised_from_u8([self.0, self.1, self.2]);
        (r, g, b)
        // Alternatively divide each component by 255 manually
    }

    fn expand_gamma(&self) -> (f32, f32, f32) {
        (
            srgb::gamma::expand_u8(self.0),
            srgb::gamma::expand_u8(self.1),
            srgb::gamma::expand_u8(self.2),
        )
        // Alternatively a convenience function is provided as well:
        // let [r, g, b] = srgb::linear_from_u8([self.0, self.1, self.2]);
        // (r, g, b)
    }

    fn to_xyz(&self) -> (f32, f32, f32) {
        let linear = srgb::linear_from_u8([self.0, self.1, self.2]);
        let [r, g, b] = srgb::xyz_from_linear(linear);
        (r, g, b)
        // Alternatively, if a custom matrix multiplication is available:
        // let [r, g, b] = matrix_product(
        //     srgb::xyz::XYZ_FROM_SRGB_MATRIX, linear);
    }
}

fn main() {
    for arg in std::env::args().into_iter().skip(1) {
        if let Some(rgb) = RGB::parse(&arg[..]) {
            println!("sRGB:       {:?}", rgb);
            println!("Normalised: {:?}", rgb.normalise());
            println!("Linear:     {:?}", rgb.expand_gamma());
            println!("XYZ:        {:?}", rgb.to_xyz());
        } else {
            eprintln!("expected ‘#rrggbb’ but got {}", arg);
        }
    }
}

No runtime deps

~0–1.6MB
~42K SLoC