colr-types 0.3.1

Color model ZSTs and marker traits for colr.
Documentation
//! Transfer functions.
//!
//! Signal encoding and decoding curves meant exclusively for use in `colr`.

#![allow(clippy::excessive_precision)]

/// Marker for a signal encoding curve.
pub trait TransferFunction: 'static {}

/// Linear transfer function. Noop.
///
/// Stored values equal linear light. The only transfer function for which
/// premultiplied alpha compositing is physically correct.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Linear;

impl TransferFunction for Linear {}

/// sRGB transfer function per IEC 61966-2-1:1999.
///
/// Piecewise function with a linear segment below threshold and a power-law
/// gamma 2.4 segment above. Dominant encoding for web content, PNG, JPEG,
/// and standard display output. Distinct from Rec. 709 despite identical primaries.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Srgb;

impl Srgb {
    /// Gain applied in the power-law segment.
    pub const ALPHA: f32 = 1.055;
    /// Exponent of the power-law segment.
    pub const GAMMA: f32 = 2.4;
    /// Slope of the linear toe.
    pub const LINEAR_SLOPE: f32 = 12.92;
    /// Linear light value at which the curve transitions to the power-law segment.
    pub const LINEAR_THRESHOLD: f32 = 0.0031308;
    /// Encoded signal value at which the curve transitions to the power-law segment.
    pub const ENCODED_THRESHOLD: f32 = 0.04045;
}

impl TransferFunction for Srgb {}

/// Rec. ITU-R BT.709-6 transfer function.
///
/// Same primaries as sRGB with a different curve, using a slope of 4.5 and an
/// effective gamma of approximately 2.222. Used for HD broadcast. Visually
/// close to sRGB but not interchangeable in precision workflows.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Rec709;

impl Rec709 {
    /// Gain applied in the power-law segment.
    pub const ALPHA: f32 = 1.09929682680944;
    /// Encoding power exponent.
    pub const POWER: f32 = 0.45;
    /// Slope of the linear toe.
    pub const LINEAR_SLOPE: f32 = 4.5;
    /// Linear light value at which the curve transitions to the power-law segment.
    pub const LINEAR_THRESHOLD: f32 = 0.018053968510807;
    /// Encoded signal value at which the curve transitions to the power-law segment.
    pub const ENCODED_THRESHOLD: f32 = 0.081242858298635;
}

impl TransferFunction for Rec709 {}

/// SMPTE ST 2084 Perceptual Quantizer transfer function.
///
/// Display-referred HDR where encoded 1.0 represents 10000 cd/m2. Used in
/// HDR10 and as the base layer in Dolby Vision.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Pq;

impl Pq {
    /// First power exponent equal to 2610/16384.
    pub const M1: f32 = 0.1593017578125;
    /// Second power exponent equal to 2523/32.
    pub const M2: f32 = 78.84375;
    /// Offset coefficient equal to 3424/4096.
    pub const C1: f32 = 0.8359375;
    /// Numerator scale coefficient equal to 2413/128.
    pub const C2: f32 = 18.8515625;
    /// Denominator scale coefficient equal to 2392/128.
    pub const C3: f32 = 18.6875;
}

impl TransferFunction for Pq {}

/// ITU-R BT.2100-2 Hybrid Log-Gamma transfer function.
///
/// Scene-referred HDR backward-compatible with SDR displays. Reference
/// white sits at approximately 0.75 on the signal scale. Used in UHD broadcast.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Hlg;

impl Hlg {
    /// Logarithmic segment coefficient a.
    pub const A: f32 = 0.17883277;
    /// Logarithmic segment offset b.
    pub const B: f32 = 0.28466892;
    /// Logarithmic segment offset c.
    pub const C: f32 = 0.5599107;
    /// Linear light value at which the curve transitions to the logarithmic segment.
    pub const LINEAR_THRESHOLD: f32 = 1.0 / 12.0;
    /// Encoded signal value at which the curve transitions to the logarithmic segment.
    pub const ENCODED_THRESHOLD: f32 = 0.5;
}

impl TransferFunction for Hlg {}

/// ProPhoto ROMM RGB transfer function per ISO 22028-2:2013.
///
/// Power-law gamma 1.8 with a small linear segment near black. Used in
/// camera raw and professional photo workflows.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ProPhoto;

impl ProPhoto {
    /// Decoding gamma exponent.
    pub const GAMMA: f32 = 1.8;
    /// Slope of the linear toe.
    pub const LINEAR_SLOPE: f32 = 16.0;
    /// Linear light value at which the curve transitions to the power-law segment.
    pub const LINEAR_THRESHOLD: f32 = 1.0 / 512.0;
    /// Encoded signal value at which the curve transitions to the power-law segment.
    pub const ENCODED_THRESHOLD: f32 = 1.0 / 32.0;
}

impl TransferFunction for ProPhoto {}

/// ACEScc logarithmic transfer function per Academy S-2014-003.
///
/// Logarithmic encoding of ACES linear data for color grading.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct AcesCc;

impl AcesCc {
    /// Minimum encoded output produced by negative linear inputs.
    pub const CUT1: f32 = -0.30136986;
    /// Denominator of the log2 normalization term.
    pub const LOG_SCALE: f32 = 17.52;
    /// Additive offset applied before normalization.
    pub const LOG_OFFSET: f32 = 9.72;
    /// Converts natural log output to log base 2 by multiplication.
    pub const LOG2_RECIP: f32 = 1.0 / core::f32::consts::LN_2;
}

impl TransferFunction for AcesCc {}

/// ACEScct quasi-logarithmic transfer function per Academy S-2016-001.
///
/// Extends ACEScc with a linear toe segment below the breakpoint.
/// Preferred for grading tools that expect a smooth near-black response.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct AcesCct;

impl AcesCct {
    /// Linear light value at the top of the linear toe segment.
    pub const X_BRK: f32 = 0.0078125;
    /// Encoded signal value at the top of the linear toe segment.
    pub const Y_BRK: f32 = 0.15525115;
    /// Slope of the linear toe segment.
    pub const A: f32 = 10.540237;
    /// Offset of the linear toe segment.
    pub const B: f32 = 0.07290553;
    /// Denominator of the log2 normalization term.
    pub const LOG_SCALE: f32 = 17.52;
    /// Additive offset applied before normalization.
    pub const LOG_OFFSET: f32 = 9.72;
    /// Converts natural log output to log base 2 by multiplication.
    pub const LOG2_RECIP: f32 = 1.0 / core::f32::consts::LN_2;
}

impl TransferFunction for AcesCct {}

/// DCI-P3 transfer function per SMPTE EG 432-1:2010.
///
/// Pure power law with gamma 2.6. Used for digital cinema projection.
/// Consumer Display P3 uses [`Srgb`] instead.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct DciP3;

impl DciP3 {
    /// Decoding gamma exponent.
    pub const GAMMA: f32 = 2.6;
}

impl TransferFunction for DciP3 {}