cint-0.3.1/.cargo_vcs_info.json0000644000000001360000000000100117720ustar { "git": { "sha1": "f567a07d25e7581ac49a9089fae6f1f2acbfe872" }, "path_in_vcs": "" }cint-0.3.1/.github/FUNDING.yml000064400000000000000000000001120072674642500137610ustar 00000000000000# These are supported funding model platforms github: termhn ko_fi: gray cint-0.3.1/.github/workflows/ci.yaml000064400000000000000000000027520072674642500154740ustar 00000000000000on: [push, pull_request] name: Continuous integration jobs: test: name: Test strategy: matrix: os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - uses: actions/cache@v2 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- ${{ runner.os }}- - uses: actions-rs/toolchain@v1 with: toolchain: stable override: true - uses: actions-rs/cargo@v1 with: command: test args: --workspace --all-targets --all-features lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/cache@v2 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- ${{ runner.os }}- - uses: actions-rs/toolchain@v1 with: toolchain: stable override: true components: rustfmt - uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check - uses: actions-rs/cargo@v1 with: command: clippy args: --all -- -D warnings cint-0.3.1/.github/workflows/rustdoc.yaml000064400000000000000000000014220072674642500165550ustar 00000000000000name: rustdoc on: push: branches: - main env: CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 RUSTUP_MAX_RETRIES: 10 jobs: rustdoc: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal override: true components: rustfmt, rust-src - name: Build Documentation run: cargo doc --all --all-features - name: Deploy Docs uses: peaceiris/actions-gh-pages@364c31d33bb99327c77b3a5438a83a357a6729ad # v3.4.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_branch: gh-pages publish_dir: ./target/doc force_orphan: truecint-0.3.1/.gitignore000064400000000000000000000000340072674642500125770ustar 00000000000000/target Cargo.lock .vscode/ cint-0.3.1/Cargo.toml0000644000000016740000000000100100000ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "cint" version = "0.3.1" authors = ["Gray Olson "] description = "A lean, minimal, and stable set of types for color interoperation between crates in Rust." homepage = "https://github.com/termhn/cint" documentation = "https://docs.rs/cint" license = "MIT OR Apache-2.0 OR Zlib" repository = "https://github.com/termhn/cint" [package.metadata.docs.rs] features = ["bytemuck"] [dependencies.bytemuck] version = "1.9.0" optional = true cint-0.3.1/Cargo.toml.orig000064400000000000000000000011220072674642500134750ustar 00000000000000[package] name = "cint" version = "0.3.1" authors = ["Gray Olson "] edition = "2018" license = "MIT OR Apache-2.0 OR Zlib" description = "A lean, minimal, and stable set of types for color interoperation between crates in Rust." documentation = "https://docs.rs/cint" homepage = "https://github.com/termhn/cint" repository = "https://github.com/termhn/cint" [package.metadata.docs.rs] features = ["bytemuck"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bytemuck = { version = "1.9.0", optional = true } cint-0.3.1/README.md000064400000000000000000000022750072674642500120770ustar 00000000000000# `cint` - `c`olor `int`erop [![crates.io](http://meritbadge.herokuapp.com/cint)](https://crates.io/crates/cint) [![docs.rs](https://docs.rs/cint/badge.svg)](https://docs.rs/cint) ## Introduction This library provides a lean, minimal, and stable set of types for color interoperation between crates in Rust. Its goal is to serve the same function that [`mint`](https://docs.rs/mint/) provides for (linear algebra) math types. It does not actually provide any conversion, math, etc. for these types, but rather serves as a stable interface that multiple libraries can rely on and then convert to their own internal representations to actually use. It is also `#![no_std]`. See [the docs](https://docs.rs/cint) for more. ## License Licensed under either of - Apache License, Version 2.0, () - MIT license () - Zlib license () at your option. ### Contribution 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. cint-0.3.1/src/lib.rs000064400000000000000000000630260072674642500125240ustar 00000000000000//! # `cint` - `c`olor `int`erop //! //! This library provides a lean, minimal, and stable set of types //! for color interoperation between crates in Rust. Its goal is to serve the same //! function that [`mint`](https://docs.rs/mint/) provides for (linear algebra) math types. //! It does not actually provide any conversion, math, etc. for these types, but rather //! serves as a stable interface that multiple libraries can rely on and then convert //! to their own internal representations to actually use. It is also `#![no_std]`. //! [`bytemuck`](https://docs.rs/bytemuck/) impls are provided with the `bytemuck` feature. //! //! # How to Use //! //! If you have no idea about color management or encoding principles but you want to //! use this crate in your own, here's a *very basic* rundown. //! //! If you have a color that you loaded from an 8-bit format like a PNG, JPG, etc., //! **or** if you have a color that you picked from some sort of online color picker //! or in Photoshop or Aseprite, then what you have is almost certainly an [`EncodedSrgb`] //! color. If you have a color that you loaded //! from a similar format but has floating point values instead of `u8` ints, then you //! almost certainly instead have a [`EncodedSrgb`] color. //! //! If you "linearized" or performed "inverse gamma correction" on such a color, then you instead //! might have a [`LinearSrgb`]. //! //! If you are more familiar with color encoding, then you'll find a collection of other color spaces //! represented, as well as the generic color types (like [`GenericColor3`]) which //! can be used if the color space you wish to use is not represented. //! //! All spaces are also collected into the [`Spaces`] enum, and you can get the variant represented //! by any of the concrete color types by taking advantage of the [`ColorType`]'s `SPACE` associated //! type, i.e. `EncodedSrgb::SPACE` will give `Spaces::EncodedSrgb`. //! //! The [`ColorInterop`] trait exists to provide a "canonical" transformation to and from `cint` types. //! Since it is often possible to convert a color to and from multiple `cint` types, and because of //! how the Rust type inference system works, it can often be inconvenient to chain together `from` //! or `into` calls from the [From]/[Into] trait. [`ColorInterop`] solves this by providing a strongly //! typed "reference" conversion to/from `cint` types. This way, you can do things like: //! //! ```rust //! let color_crate1 = color_crate2.into_cint().into(); //! // or //! let color_crate2 = ColorCrate2::from_cint(color_crate1.into()); //! ``` //! //! which would otherwise be quite inconvenient. **Provider crates** (those that provide their own color //! types) should implement the relevant [`From`]/[`Into`] implementations to and from `cint` types, and //! also the [ColorInterop] trait once for each color type. The [`into_cint`][ColorInterop::into_cint] and //! [`from_cint`][ColorInterop::from_cint] methods will then be provided automatically. //! //! ## Colors with alpha channels //! //! `cint` provides the [`Alpha`] and [`PremultipliedAlpha`] //! structs, which are generic over the inner `ColorTy`. //! To represent an [`EncodedSrgb`] color with a premultiplied alpha component, //! you'd use [`PremultipliedAlpha>`]. If, on the other hand, you want to represent //! an [`Oklab`] color with an independent alpha component, you'd use [`Alpha>`] #![no_std] #![allow(unsafe_code)] #[cfg(feature = "bytemuck")] use bytemuck::{Pod, Zeroable}; /// A trait used to simpify the interface of the [`Alpha`] and [`PremultipliedAlpha`] types and /// allow use with [`Spaces`] enum. pub trait ColorType { type ComponentTy: Copy; const SPACE: Spaces; const NUM_COMPONENTS: usize; } /// A trait that should be implemented by provider crates on their local color types so that you can call /// `color.to_cint()` and `Color::from_cint(cint_color)`. /// /// Provider crates should also do relevant `From`/`Into` impls, but [`ColorInterop`] provides a "canonical" /// transformation to the closest `cint` color type. pub trait ColorInterop where Self: Into<::CintTy>, { type CintTy: Into; /// Convert `self` into its canonical `cint` type. fn from_cint(col: Self::CintTy) -> Self { col.into() } /// Create a `Self` from its canonical `cint` type. fn into_cint(self) -> Self::CintTy { self.into() } } /// A color with an alpha component. /// /// The color components and alpha component are completely separate. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] #[repr(C)] pub struct Alpha { /// The contained color, which is completely separate from the `alpha` value. pub color: ColorTy, /// The alpha component. pub alpha: ColorTy::ComponentTy, } impl ColorType for Alpha { type ComponentTy = BaseColorTy::ComponentTy; const SPACE: Spaces = BaseColorTy::SPACE; const NUM_COMPONENTS: usize = BaseColorTy::NUM_COMPONENTS + 1; } #[cfg(feature = "bytemuck")] unsafe impl Zeroable for Alpha {} #[cfg(feature = "bytemuck")] unsafe impl Pod for Alpha {} /// A premultiplied color with an alpha component. /// /// The color components have been premultiplied by the alpha component. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub struct PremultipliedAlpha { /// The contained color, which has been premultiplied with `alpha` pub color: ColorTy, /// The alpha component. pub alpha: ColorTy::ComponentTy, } impl ColorType for PremultipliedAlpha { type ComponentTy = BaseColorTy::ComponentTy; const SPACE: Spaces = BaseColorTy::SPACE; const NUM_COMPONENTS: usize = BaseColorTy::NUM_COMPONENTS + 1; } #[cfg(feature = "bytemuck")] unsafe impl Zeroable for PremultipliedAlpha {} #[cfg(feature = "bytemuck")] unsafe impl Pod for PremultipliedAlpha {} macro_rules! color_struct { { $(#[$doc:meta])* $name:ident<$default_component_ty:ty, $num_components:literal> { $($(#[$compdoc:meta])+ $compname:ident,)+ } } => { $(#[$doc])* #[repr(C)] #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub struct $name { $($(#[$compdoc])+ pub $compname: ComponentTy,)+ } impl ColorType for $name { type ComponentTy = CTy; const SPACE: Spaces = Spaces::$name; const NUM_COMPONENTS: usize = $num_components; } #[cfg(feature = "bytemuck")] unsafe impl Zeroable for $name {} #[cfg(feature = "bytemuck")] unsafe impl Pod for $name {} impl From<[ComponentTy; $num_components]> for $name { fn from([$($compname),+]: [ComponentTy; $num_components]) -> $name { $name { $($compname,)+ } } } #[allow(clippy::from_over_into)] impl Into<[ComponentTy; $num_components]> for $name { fn into(self) -> [ComponentTy; $num_components] { let $name { $($compname,)+ } = self; [$($compname),+] } } impl AsRef<[ComponentTy; $num_components]> for $name { fn as_ref(&self) -> &[ComponentTy; $num_components] { // SAFETY: same layout is guaranteed by repr C unsafe { &*(self as *const $name as *const [ComponentTy; $num_components]) } } } impl AsMut<[ComponentTy; $num_components]> for $name { fn as_mut(&mut self) -> &mut [ComponentTy; $num_components] { // SAFETY: same layout is guaranteed by repr C unsafe { &mut *(self as *mut $name as *mut [ComponentTy; $num_components]) } } } macro_rules! impl_alpha_traits { ($alphaty:ident) => { impl From<$alphaty<$name>> for $name { fn from(col_alpha: $alphaty<$name>) -> $name { col_alpha.color } } impl From<[ComponentTy; $num_components + 1]> for $alphaty<$name> { fn from([$($compname,)+ alpha]: [ComponentTy; $num_components + 1]) -> $alphaty<$name> { $alphaty { color: $name::from([$($compname,)+]), alpha, } } } #[allow(clippy::from_over_into)] impl Into<[ComponentTy; $num_components + 1]> for $alphaty<$name> { fn into(self) -> [ComponentTy; $num_components + 1] { let $alphaty { color, alpha } = self; let $name { $($compname,)+ } = color; [$($compname,)+ alpha] } } impl AsRef<[ComponentTy; $num_components + 1]> for $alphaty<$name> { fn as_ref(&self) -> &[ComponentTy; $num_components + 1] { // SAFETY: same layout is guaranteed by repr C unsafe { &*(self as *const $alphaty<$name> as *const [ComponentTy; $num_components + 1]) } } } impl AsMut<[ComponentTy; $num_components + 1]> for $alphaty<$name> { fn as_mut(&mut self) -> &mut [ComponentTy; $num_components + 1] { // SAFETY: same layout is guaranteed by repr C unsafe { &mut *(self as *mut $alphaty<$name> as *mut [ComponentTy; $num_components + 1]) } } } } } impl_alpha_traits!(Alpha); impl_alpha_traits!(PremultipliedAlpha); }; } macro_rules! color_spaces { { $($(#[$space_doc:meta])* $space_name:ident<$default_component_ty:ty, $num_components:literal> { $($(#[$comp_doc:meta])+ $comp_name:ident,)+ })* } => { /// An enum with a variant for each of the color spaces /// supported by the library. Useful for tracking as metadata /// in something like an image type, and for runtime-determined color types. #[repr(u32)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Spaces { $( $(#[$space_doc])* $space_name, )* } impl Spaces { pub fn num_components(&self) -> usize { match *self { $( Self::$space_name => $num_components, )* } } } $( color_struct! { $(#[$space_doc])* $space_name<$default_component_ty, $num_components> { $( $(#[$comp_doc])+ $comp_name,)+ } } )* } } color_spaces! { /// A color in the encoded sRGB color space. /// /// This color space uses the sRGB/Rec.709 primaries, D65 white point, /// and sRGB transfer functions. The encoded version is nonlinear, with the /// sRGB OETF, aka "gamma compensation", applied. EncodedSrgb { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the linear (decoded) sRGB color space. /// /// This color space uses the sRGB/Rec.709 primaries, D65 white point, /// and sRGB transfer functions. This version is linear, with the /// sRGB EOTF, aka "inverse gamma compensation", applied in order to /// decode it from [`EncodedSrgb`] LinearSrgb { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the encoded Rec.709/BT.709 color space. /// /// This color space uses the BT.709 primaries, D65 white point, /// and BT.601 (reused in BT.709) transfer function. The encoded version is nonlinear, with the /// BT.601 OETF applied. EncodedRec709 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the Rec.709/BT.709 color space. /// /// This color space uses the BT.709 primaries, D65 white point, /// and BT.601 (reused in BT.709) transfer function. This version is linear, without the /// BT.601 OETF applied. Rec709 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in a generic color space that can be represented by 3 components. The user /// is responsible for ensuring that the correct color space is respected. GenericColor3 { /// The first component. x, /// The second component. y, /// The third component. z, } /// A color in a generic color space that can be represented by 1 component. The user /// is responsible for ensuring that the correct color space is respected. GenericColor1 { /// The first component. x, } /// A single-channel CIE luminance. Luminance { /// CIE luminance. l, } /// A single-channel CIE luma (non-linear transform from luminance). Luma { /// CIE luminance. l, } /// A color in the ACEScg color space. /// /// This color space uses the ACES AP1 primaries and D60 white point. AcesCg { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the ACES 2065-1 color space. /// /// This color space uses the ACES AP0 primaries and D60 white point. Aces2065 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the ACEScc color space. /// /// This color space uses the ACES AP1 primaries and D60 white point /// and a pure logarithmic transfer function. AcesCc { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the ACEScct color space. /// /// This color space uses the ACES AP1 primaries and D60 white point /// and a logarithmic transfer function with a toe such that values /// are able to go negative. AcesCct { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the Display P3 (aka P3 D65) color space. /// /// This color space uses the P3 primaries and D65 white point /// and sRGB transfer functions. This version is linear, /// without the sRGB OETF applied. DisplayP3 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the Display P3 (aka P3 D65) color space. /// /// This color space uses the P3 primaries and D65 white point /// and sRGB transfer functions. This encoded version is nonlinear, /// with the sRGB OETF applied. EncodedDisplayP3 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the DCI-P3 (aka P3 DCI and P3 D60) color space. /// /// If you are looking for the P3 which is used on new Apple displays, see /// [`DisplayP3`] instead. /// /// This color space uses the P3 primaries and D60 white point. DciP3 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the X'Y'Z' color space, a DCI specification used for digital cinema mastering. /// /// This color space uses the CIE XYZ primaries, with special DCI white point and pure 2.6 gamma encoding. DciXYZPrime { /// The X' component. x, /// The Y' component. y, /// The Z' component. z, } /// A color in the BT.2020 color space. /// /// This color space uses the BT.2020 primaries and D65 white point. Bt2020 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the encoded BT.2020 color space. /// /// This color space uses the BT.2020 primaries and D65 white point and /// the BT.2020 transfer functions (equivalent to BT.601 transfer functions /// but with higher precision). This encoded version is nonlinear, with the /// BT.2020/BT.601 OETF applied. EncodedBt2020 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the BT.2100 color space. /// /// This color space uses the BT.2020 primaries and D65 white point. Bt2100 { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the encoded BT.2100 color space with PQ (Perceptual Quantizer) /// transfer function. /// /// This color space uses the BT.2020 primaries and D65 white point and /// the ST 2084/"PQ" transfer function. It is nonlinear. EncodedBt2100PQ { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the encoded BT.2100 color space with HLG (Hybrid Log-Gamma) /// transfer function. /// /// This color space uses the BT.2020 primaries and D65 white point and /// the HLG transfer function. It is nonlinear. EncodedBt2100HLG { /// The red component. r, /// The green component. g, /// The blue component. b, } /// A color in the ICtCp color space with PQ (Perceptual Quantizer) /// nonlinearity. /// /// This color space is based on the BT.2020 primaries and D65 white point, /// but is not an RGB color space. Instead it is a roughly perceptual color /// space meant to more efficiently encode HDR content. ICtCpPQ { /// The I (intensity) component. i, /// The Ct (chroma-tritan) component. ct, /// The Cp (chroma-protan) component. cp, } /// A color in the ICtCp color space with HLG (Hybrid Log-Gamma) /// nonlinearity. /// /// This color space is based on the BT.2020 primaries and D65 white point, /// but is not an RGB color space. Instead it is a roughly perceptual color /// space meant to more efficiently encode HDR content. ICtCpHLG { /// The I (intensity) component. i, /// The Ct (chroma-tritan) component. ct, /// The Cp (chroma-protan) component. cp, } /// A color in the CIE XYZ color space. /// /// This color space uses the CIE XYZ primaries and D65 white point. CieXYZ { /// The X component. x, /// The Y component. y, /// The Z component. z, } /// A color in the CIE L\*a\*b\* color space. CieLab { /// The L (lightness) component. Varies from 0 to 100. l, /// The a component, representing green-red chroma difference. a, /// The b component, representing blue-yellow chroma difference. b, } /// A color in the CIE L\*C\*h° color space. CieLCh { /// The L (lightness) component. Varies from 0 to 100. l, /// The C (chroma) component. Varies from 0 to a hue dependent maximum. c, /// The h (hue) component. Varies from -PI to PI. h, } /// A color in the Oklab color space. Oklab { /// The L (lightness) component. Varies from 0 to 1 l, /// The a component, representing green-red chroma difference. a, /// The b component, representing blue-yellow chroma difference. b, } /// A color in the Oklch color space (a transformation from Oklab to LCh° coordinates). Oklch { /// The L (lightness) component. Varies from 0 to 1. l, /// The C (chroma) component. Varies from 0 to a hue dependent maximum. c, /// The h (hue) component. Varies from -PI to PI. h, } /// A color in the HSL color space. /// /// Since HSL is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as the linear sRGB space, as that is /// the most common case. Hsl { /// The H (hue) component. Varies from 0 to 1. h, /// The S (saturation) component. Varies from 0 to 1. s, /// The L (lightness) component. Varies from 0 to 1. l, } /// A color in the HSV color space. /// /// Since HSV is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as the linear sRGB space, as that is /// the most common case. Hsv { /// The H (hue) component. Varies from 0 to 1. h, /// The S (saturation) component. Varies from 0 to 1. s, /// The V (value) component. Varies from 0 to 1. v, } /// A color in the YCbCr color space. See discussion of the difference between YCbCr, YUV, and /// YPbPr in [YCbCr Wikipedia article](https://en.wikipedia.org/wiki/YCbCr) /// /// Since YCbCr is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as being converted from the LinearSrgb color space. YCbCr { /// The Y (luminance) component. y, /// The Cb (chroma-blue/yellow) component. cb, /// The Cr (chroma-red/green) component. cr, } /// A color in the Y'CbCr color space. See discussion of the difference between YCbCr, Y'CbCr, /// YUV, YPbPr, and Y'PbPr in the [YCbCr Wikipedia article](https://en.wikipedia.org/wiki/YCbCr) /// /// Since Y'CbCr is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as being converted from the EncodedSrgb color space. YPrimeCbCr { /// The Y' (luma) component. y, /// The Cb (chroma-blue/yellow) component. cb, /// The Cr (chroma-red/green) component. cr, } /// A color in the YPbPr color space. See discussion of the difference between YCbCr, /// YUV, YPbPr, and Y'PbPr in the [YCbCr Wikipedia article](https://en.wikipedia.org/wiki/YCbCr) /// /// Since YPbPr is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as being converted from the LinearSrgb color space. YPbPr { /// The Y (luminance) component. y, /// The Pb (chroma-blue/yellow) component. pb, /// The Pr (chroma-red/green) component. pr, } /// A color in the Y'PbPr color space. See discussion of the difference between YCbCr, /// YUV, YPbPr, and Y'PbPr in the [YCbCr Wikipedia article](https://en.wikipedia.org/wiki/YCbCr) /// /// Since Y'PbPr is a relative color space, it is required to know the RGB space which /// it was transformed from. We define this as being converted from the EncodedSrgb color space. YPrimePbPr { /// The Y' (luma) component. y, /// The Pb (chroma-blue/yellow) component. pb, /// The Pr (chroma-red/green) component. pr, } /// A color in the YUV color space. See discussion of the difference between YCbCr, YUV, and /// YPbPr in [YCbCr Wikipedia article](https://en.wikipedia.org/wiki/YCbCr) Yuv { /// The Y (luminance) component. y, /// The U (chroma-blue/yellow) component. u, /// The V (chroma-red/green) component. v, } /// A color in the YCxCz (also called YyCxCz) color space, originally defined in "Optimized /// universal color palette design for error diffusion" by B. W. Kolpatzik and C. A. Bouman. /// Can be thought of as a "linear CIE Lab". YCxCz { /// The Yy (luminance) component. y, /// The Cx (chroma difference blue/yellow) component cx, /// The Cz (chroma difference red/green) component cz, } }