diff --git a/palette/src/encoding.rs b/palette/src/encoding.rs index b4f0f9d61..a1674018e 100644 --- a/palette/src/encoding.rs +++ b/palette/src/encoding.rs @@ -7,10 +7,12 @@ pub use self::gamma::{F2p2, Gamma}; pub use self::linear::Linear; +pub use self::rec_standards::{Rec2020, Rec709}; pub use self::srgb::Srgb; pub mod gamma; pub mod linear; +pub mod rec_standards; pub mod srgb; /// A transfer function from linear space. diff --git a/palette/src/encoding/rec_standards.rs b/palette/src/encoding/rec_standards.rs new file mode 100644 index 000000000..a136f4391 --- /dev/null +++ b/palette/src/encoding/rec_standards.rs @@ -0,0 +1,298 @@ +//! The ITU-R Recommendation BT.2020 (Rec. 2020) and BT.709 (Rec. 709) standards and their +//! associated transfer function. + +use crate::{ + bool_mask::LazySelect, + encoding::{FromLinear, IntoLinear, Srgb}, + luma::LumaStandard, + num::{Arithmetics, MulAdd, MulSub, PartialCmp, Powf, Real}, + rgb::{Primaries, RgbSpace, RgbStandard}, + white_point::{Any, D65}, + Mat3, Yxy, +}; + +use lookup_tables::*; + +mod lookup_tables; + +/// The Rec. 2020 standard, color space, and transfer function. +/// +/// # As transfer function +/// +/// `Rec2020` will not use any kind of approximation when converting from `T` to +/// `T`. This involves calls to `powf`, which may make it too slow for certain +/// applications. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Rec2020; + +impl Primaries for Rec2020 { + // Primary values taken from ITU specification: + // https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-2-201510-I!!PDF-E.pdf + fn red() -> Yxy { + Yxy::new(T::from_f64(0.708), T::from_f64(0.292), T::from_f64(0.2627)) + } + fn green() -> Yxy { + Yxy::new(T::from_f64(0.170), T::from_f64(0.797), T::from_f64(0.6780)) + } + fn blue() -> Yxy { + Yxy::new(T::from_f64(0.131), T::from_f64(0.046), T::from_f64(0.0593)) + } +} + +impl RgbSpace for Rec2020 { + type Primaries = Rec2020; + type WhitePoint = D65; + + #[rustfmt::skip] + #[inline(always)] + fn rgb_to_xyz_matrix() -> Option> { + // Matrix calculated using specified primary values and white point + // using formulas from http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + Some([ + 0.6370102, 0.1446150, 0.1688448, + 0.2627217, 0.6779893, 0.0592890, + 0.0000000, 0.0280723, 1.0607577, + ]) + } + + #[rustfmt::skip] + #[inline(always)] + fn xyz_to_rgb_matrix() -> Option> { + // Matrix calculated using specified primary values and white point + // using formulas from http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + Some([ + 1.7165107, -0.3556417, -0.2533455, + -0.6666930, 1.6165022, 0.0157688, + 0.0176436, -0.0427798, 0.9423051, + ]) + } +} + +impl RgbStandard for Rec2020 { + type Space = Rec2020; + type TransferFn = RecOetf; +} + +impl LumaStandard for Rec2020 { + type WhitePoint = D65; + type TransferFn = RecOetf; +} + +/// The Rec. 709 standard, color space, and transfer function. +/// +/// # As transfer function +/// +/// `Rec709` will not use any kind of approximation when converting from `T` to +/// `T`. This involves calls to `powf`, which may make it too slow for certain +/// applications. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Rec709; + +impl RgbStandard for Rec709 { + type Space = Srgb; + type TransferFn = RecOetf; +} + +impl LumaStandard for Rec709 { + type WhitePoint = D65; + type TransferFn = RecOetf; +} + +/// The opto-electronic transfer function used in standard dynamic range (SDR) +/// standards by the ITU-R such as [`Rec709`] and [`Rec2020`]. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct RecOetf; + +const ALPHA: f64 = 1.09929682680944; +const BETA: f64 = 0.018053968510807; + +impl IntoLinear for RecOetf +where + T: Real + Powf + MulAdd + Arithmetics + PartialCmp + Clone, + T::Mask: LazySelect, +{ + #[inline] + fn into_linear(encoded: T) -> T { + lazy_select! { + if encoded.lt(&T::from_f64(4.5*BETA)) => T::from_f64(1.0 / 4.5) * &encoded, + else => encoded.clone().mul_add(T::from_f64(1.0 / ALPHA), T::from_f64(1.0 - 1.0 / ALPHA)).powf(T::from_f64(1.0 / 0.45)) + } + } +} + +impl FromLinear for RecOetf +where + T: Real + Powf + MulSub + Arithmetics + PartialCmp + Clone, + T::Mask: LazySelect, +{ + #[inline] + fn from_linear(linear: T) -> T { + lazy_select! { + if linear.lt(&T::from_f64(BETA)) => T::from_f64(4.5) * &linear, + else => linear.clone().powf(T::from_f64(0.45)).mul_sub(T::from_f64(ALPHA), T::from_f64(ALPHA - 1.0)) + } + } +} + +impl IntoLinear for RecOetf { + #[inline] + fn into_linear(encoded: u8) -> f32 { + REC_OETF_U8_TO_F32[encoded as usize] + } +} + +impl FromLinear for RecOetf { + #[inline] + fn from_linear(linear: f32) -> u8 { + // Algorithm modeled closely off of `f32_to_srgb8` from fast-srgb8 crate + const MAX_FLOAT_BITS: u32 = 0x3f7fffff; // 1.0 - f32::EPSILON + const MIN_FLOAT_BITS: u32 = 0x39000000; // 2^(-13) + let max_float = f32::from_bits(MAX_FLOAT_BITS); + let min_float = f32::from_bits(MIN_FLOAT_BITS); + + let mut input = linear; + // Implemented this way to map NaN to `min_float` + if input.partial_cmp(&min_float) != Some(core::cmp::Ordering::Greater) { + input = min_float; + } else if input > max_float { + input = max_float; + } + let input_bits = input.to_bits(); + #[cfg(test)] + { + debug_assert!((MIN_FLOAT_BITS..=MAX_FLOAT_BITS).contains(&input_bits)); + } + // Safety: all input floats are clamped into the {min_float, max_float} range, + // which turns out in this case to guarantee that their bitwise reprs are + // clamped to the {MIN_FLOAT_BITS, MAX_FLOAT_BITS} range (guaranteed by the + // fact that min_float/max_float are the normal, finite, the same sign, and + // not zero). + // + // Because of that, the smallest result of `input_bits - MIN_FLOAT_BITS` is 0 + // (when `input_bits` is `MIN_FLOAT_BITS`), and the largest is `0x067fffff`, + // (when `input_bits` is `MAX_FLOAT_BITS`). `0x067fffff >> 20` is 0x67, e.g. 103, + // and thus all possible results are inbounds for the (104 item) table. + // This is all verified in test code. + // + // Note that the compiler can't figure this out on it's own, so the + // get_unchecked does help some. + let entry = { + let i = ((input_bits - MIN_FLOAT_BITS) >> 20) as usize; + #[cfg(test)] + { + debug_assert!(TO_REC_OETF_U8.get(i).is_some()); + } + unsafe { *TO_REC_OETF_U8.get_unchecked(i) } + }; + + let bias = (entry >> 16) << 9; + let scale = entry & 0xffff; + + let t = (input_bits >> 12) & 0xff; + let res = (bias + scale * t) >> 16; + #[cfg(test)] + { + debug_assert!(res < 256, "{}", res); + } + res as u8 + } +} + +impl IntoLinear for RecOetf { + #[inline] + fn into_linear(encoded: u8) -> f64 { + REC_OETF_U8_TO_F64[encoded as usize] + } +} + +impl FromLinear for RecOetf { + #[inline] + fn from_linear(linear: f64) -> u8 { + RecOetf::from_linear(linear as f32) + } +} + +#[cfg(test)] +mod test { + #[cfg(feature = "approx")] + mod conversion { + use crate::{ + encoding::Rec2020, + matrix::{matrix_inverse, rgb_to_xyz_matrix}, + rgb::RgbSpace, + }; + + #[test] + fn rgb_to_xyz() { + let dynamic = rgb_to_xyz_matrix::(); + let constant = Rec2020::rgb_to_xyz_matrix().unwrap(); + assert_relative_eq!(dynamic[..], constant[..], epsilon = 0.0000001); + } + + #[test] + fn xyz_to_rgb() { + let dynamic = matrix_inverse(rgb_to_xyz_matrix::()); + let constant = Rec2020::xyz_to_rgb_matrix().unwrap(); + assert_relative_eq!(dynamic[..], constant[..], epsilon = 0.0000001); + } + } + + #[cfg(feature = "approx")] + mod transfer { + use crate::encoding::{rec_standards::RecOetf, FromLinear, IntoLinear}; + + #[test] + fn lin_to_enc_to_lin() { + for i in 0..=100 { + let linear = i as f64 / 100.0; + let encoded: f64 = RecOetf::from_linear(linear); + assert_relative_eq!(linear, RecOetf::into_linear(encoded), epsilon = 0.0000001); + } + } + + #[test] + fn enc_to_lin_to_enc() { + for i in 0..=100 { + let encoded = i as f64 / 100.0; + let linear: f64 = RecOetf::into_linear(encoded); + assert_relative_eq!(encoded, RecOetf::from_linear(linear), epsilon = 0.0000001); + } + } + + #[test] + fn test_u8_f32_into_impl() { + for i in 0..=255u8 { + let u8_impl: f32 = RecOetf::into_linear(i); + let f32_impl = RecOetf::into_linear(i as f32 / 255.0); + assert_relative_eq!(u8_impl, f32_impl, epsilon = 0.0000001); + } + } + + #[test] + fn test_u8_f64_into_impl() { + for i in 0..=255u8 { + let u8_impl: f64 = RecOetf::into_linear(i); + let f64_impl = RecOetf::into_linear(i as f64 / 255.0); + assert_relative_eq!(u8_impl, f64_impl, epsilon = 0.0000001); + } + } + + #[test] + fn u8_to_f32_to_u8() { + for expected in 0u8..=255u8 { + let linear: f32 = RecOetf::into_linear(expected); + let result: u8 = RecOetf::from_linear(linear); + assert_eq!(result, expected); + } + } + + #[test] + fn u8_to_f64_to_u8() { + for expected in 0u8..=255u8 { + let linear: f64 = RecOetf::into_linear(expected); + let result: u8 = RecOetf::from_linear(linear); + assert_eq!(result, expected); + } + } + } +} diff --git a/palette/src/encoding/rec_standards/lookup_tables.rs b/palette/src/encoding/rec_standards/lookup_tables.rs new file mode 100644 index 000000000..f6250d596 --- /dev/null +++ b/palette/src/encoding/rec_standards/lookup_tables.rs @@ -0,0 +1,533 @@ +pub const REC_OETF_U8_TO_F32: [f32; 256] = [ + 0.0, + 0.0008714598, + 0.0017429196, + 0.0026143792, + 0.003485839, + 0.004357299, + 0.0052287583, + 0.006100218, + 0.006971678, + 0.007843138, + 0.008714598, + 0.009586057, + 0.010457517, + 0.011328977, + 0.012200436, + 0.013071896, + 0.013943356, + 0.0148148155, + 0.015686275, + 0.016557734, + 0.017429195, + 0.01830158, + 0.019191194, + 0.020104086, + 0.021040367, + 0.022000136, + 0.022983504, + 0.023990571, + 0.025021447, + 0.026076222, + 0.027154997, + 0.028257878, + 0.02938495, + 0.030536316, + 0.031712063, + 0.032912288, + 0.03413708, + 0.03538653, + 0.036660723, + 0.03795976, + 0.039283704, + 0.040632658, + 0.04200671, + 0.04340593, + 0.044830408, + 0.04628022, + 0.047755457, + 0.0492562, + 0.050782513, + 0.052334484, + 0.053912185, + 0.0555157, + 0.057145096, + 0.05880047, + 0.060481865, + 0.06218937, + 0.06392305, + 0.06568299, + 0.06746926, + 0.069281936, + 0.07112106, + 0.07298672, + 0.07487899, + 0.07679793, + 0.07874362, + 0.08071611, + 0.08271547, + 0.084741764, + 0.08679507, + 0.08887546, + 0.090982966, + 0.09311767, + 0.09527963, + 0.09746891, + 0.09968559, + 0.1019297, + 0.10420135, + 0.10650054, + 0.10882736, + 0.11118187, + 0.11356413, + 0.115974195, + 0.11841215, + 0.120878, + 0.12337184, + 0.12589371, + 0.12844367, + 0.1310218, + 0.13362814, + 0.13626273, + 0.13892564, + 0.14161693, + 0.14433663, + 0.14708482, + 0.14986154, + 0.15266688, + 0.15550083, + 0.15836348, + 0.16125488, + 0.16417508, + 0.16712412, + 0.17010209, + 0.173109, + 0.1761449, + 0.17920986, + 0.18230392, + 0.18542714, + 0.18857959, + 0.19176127, + 0.19497225, + 0.19821258, + 0.20148231, + 0.20478149, + 0.20811017, + 0.2114684, + 0.2148562, + 0.21827365, + 0.22172078, + 0.22519764, + 0.22870427, + 0.23224074, + 0.23580706, + 0.2394033, + 0.24302956, + 0.24668577, + 0.25037202, + 0.2540884, + 0.25783488, + 0.26161155, + 0.26541844, + 0.2692557, + 0.27312317, + 0.27702102, + 0.28094926, + 0.28490794, + 0.28889713, + 0.2929168, + 0.2969671, + 0.30104795, + 0.3051595, + 0.30930173, + 0.3134747, + 0.31767845, + 0.3219131, + 0.32617852, + 0.33047485, + 0.33480212, + 0.33916035, + 0.34354964, + 0.34796998, + 0.3524214, + 0.356904, + 0.36141774, + 0.3659627, + 0.37053895, + 0.3751465, + 0.37978545, + 0.38445568, + 0.38915735, + 0.39389047, + 0.39865506, + 0.40345117, + 0.40827888, + 0.41313815, + 0.4180291, + 0.4229517, + 0.42790604, + 0.4328921, + 0.43791005, + 0.44295976, + 0.4480413, + 0.45315474, + 0.45830014, + 0.4634775, + 0.46868685, + 0.47392824, + 0.4792017, + 0.4845073, + 0.48984504, + 0.49521497, + 0.5006171, + 0.5060516, + 0.5115183, + 0.5170173, + 0.5225486, + 0.5281124, + 0.5337086, + 0.5393372, + 0.54499835, + 0.550692, + 0.55641824, + 0.56217706, + 0.56796855, + 0.57379264, + 0.57964957, + 0.5855391, + 0.5914614, + 0.5974165, + 0.6034044, + 0.60942525, + 0.61547893, + 0.6215655, + 0.62768507, + 0.63383764, + 0.64002323, + 0.6462419, + 0.6524937, + 0.65877855, + 0.6650966, + 0.67144775, + 0.6778322, + 0.6842498, + 0.6907007, + 0.697185, + 0.7037025, + 0.7102535, + 0.7168378, + 0.7234556, + 0.73010683, + 0.7367917, + 0.74350995, + 0.7502617, + 0.7570471, + 0.7638661, + 0.7707188, + 0.7776051, + 0.78452516, + 0.79147893, + 0.7984665, + 0.8054878, + 0.812543, + 0.819632, + 0.826755, + 0.83391184, + 0.8411026, + 0.8483273, + 0.855586, + 0.8628788, + 0.8702056, + 0.87756646, + 0.8849615, + 0.89239067, + 0.899854, + 0.9073515, + 0.91488343, + 0.9224494, + 0.9300497, + 0.93768436, + 0.9453533, + 0.95305663, + 0.9607944, + 0.96856654, + 0.97637314, + 0.98421425, + 0.99208987, + 1.0, +]; + +pub const REC_OETF_U8_TO_F64: [f64; 256] = [ + 0.0, + 0.0008714596949891067, + 0.0017429193899782135, + 0.00261437908496732, + 0.003485838779956427, + 0.004357298474945533, + 0.00522875816993464, + 0.006100217864923747, + 0.006971677559912854, + 0.00784313725490196, + 0.008714596949891067, + 0.009586056644880174, + 0.01045751633986928, + 0.011328976034858386, + 0.012200435729847494, + 0.0130718954248366, + 0.013943355119825708, + 0.014814814814814814, + 0.01568627450980392, + 0.016557734204793027, + 0.017429193899782133, + 0.018301580944001385, + 0.019191196302792108, + 0.02010408907733394, + 0.02104036769936566, + 0.02200013886887406, + 0.022983507616046173, + 0.02399057735982643, + 0.025021449963326982, + 0.02607622578631685, + 0.02715500373499541, + 0.028257881309237818, + 0.029384954647483977, + 0.030536318569427956, + 0.03171206661665195, + 0.0329122910913372, + 0.03413708309317338, + 0.03538653255457884, + 0.03666072827433487, + 0.03795975794972993, + 0.03928370820730171, + 0.04063266463225952, + 0.04200671179666235, + 0.04340593328642348, + 0.044830411727206886, + 0.04628022880927653, + 0.04775546531135519, + 0.04925620112354599, + 0.05078251526936555, + 0.05233448592693549, + 0.05391219044937511, + 0.055515705384435586, + 0.05714510649341376, + 0.05880046876938103, + 0.060481866454760204, + 0.06218937305828221, + 0.06392306137135181, + 0.06568300348384969, + 0.06746927079939749, + 0.06928193405011016, + 0.0711210633108584, + 0.07298672801306363, + 0.07487899695804565, + 0.0767979383299428, + 0.07874361970822263, + 0.08071610807980109, + 0.0827154698507861, + 0.08474177085786165, + 0.086795076379327, + 0.08887545114580514, + 0.09098295935063361, + 0.09311766465995065, + 0.09527963022248875, + 0.09746891867908646, + 0.09968559217193024, + 0.10192971235353562, + 0.10420134039547894, + 0.10650053699688747, + 0.10882736239269793, + 0.11118187636169172, + 0.11356413823431478, + 0.1159742069002902, + 0.11841214081603028, + 0.12087799801185621, + 0.12337183609903125, + 0.12589371227661408, + 0.12844368333813896, + 0.1310218056781277, + 0.13362813529844056, + 0.13626272781446952, + 0.13892563846118136, + 0.14161692209901344, + 0.14433663321962847, + 0.14708482595153244, + 0.1498615540655592, + 0.1526668709802277, + 0.15550082976697394, + 0.15836348315526344, + 0.16125488353758632, + 0.1641750829743393, + 0.16712413319859887, + 0.17010208562078702, + 0.17310899133323493, + 0.17614490111464548, + 0.17920986543446, + 0.18230393445712956, + 0.18542715804629553, + 0.188579585768881, + 0.19176126689909598, + 0.19497225042235886, + 0.19821258503913605, + 0.2014823191687029, + 0.2047815009528274, + 0.20811017825937883, + 0.2114683986858642, + 0.214856209562893, + 0.21827365795757392, + 0.2217207906768443, + 0.22519765427073363, + 0.2287042950355644, + 0.23224075901709065, + 0.2358070920135763, + 0.23940333957881532, + 0.24302954702509297, + 0.24668575942609436, + 0.2503720216197555, + 0.25408837821106356, + 0.25783487357480467, + 0.2616115518582615, + 0.2654184569838623, + 0.2692556326517808, + 0.2731231223424909, + 0.27702096931927483, + 0.2809492166306873, + 0.28490790711297576, + 0.2888970833924589, + 0.29291678788786385, + 0.2969670628126217, + 0.3010479501771253, + 0.30515949179094737, + 0.30930172926502175, + 0.3134747040137867, + 0.31767845725729355, + 0.32191303002328003, + 0.326178463149208, + 0.3304747972842693, + 0.3348020728913574, + 0.3391603302490083, + 0.34354960945330887, + 0.34796995041977424, + 0.3524213928851976, + 0.3569039764094671, + 0.36141774037735663, + 0.36596272400028784, + 0.3705389663180635, + 0.3751465062005754, + 0.3797853823494851, + 0.3844556332998791, + 0.38915729742189814, + 0.3938904129223426, + 0.3986550178462535, + 0.40345115007846843, + 0.408278847345156, + 0.41313814721532627, + 0.4180290871023199, + 0.4229517042652734, + 0.42790603581056524, + 0.43289211869324007, + 0.43790998971841116, + 0.4429596855426442, + 0.44804124267532036, + 0.4531546974799807, + 0.4583000861756504, + 0.4634774448381444, + 0.46868680940135693, + 0.4739282156585292, + 0.47920169926350287, + 0.4845072957319539, + 0.4898450404426113, + 0.49521496863845715, + 0.5006171154279119, + 0.5060515157860027, + 0.5115182045555167, + 0.5170172164481376, + 0.5225485860455683, + 0.5281123478006384, + 0.5337085360383961, + 0.5393371849571862, + 0.5449983286297148, + 0.5506920010040989, + 0.556418235904903, + 0.5621770670341617, + 0.5679685279723907, + 0.5737926521795822, + 0.5796494729961896, + 0.5855390236441004, + 0.5914613372275938, + 0.5974164467342884, + 0.6034043850360787, + 0.6094251848900586, + 0.6154788789394324, + 0.6215654997144172, + 0.6276850796331327, + 0.6338376510024797, + 0.6400232460190087, + 0.6462418967697774, + 0.652493635233199, + 0.6587784932798784, + 0.6650965026734394, + 0.6714476950713434, + 0.6778321020256947, + 0.6842497549840402, + 0.6907006852901576, + 0.6971849241848346, + 0.7037025028066392, + 0.7102534521926807, + 0.7168378032793632, + 0.7234555869031283, + 0.7301068338011902, + 0.7367915746122637, + 0.7435098398772821, + 0.7502616600401067, + 0.7570470654482304, + 0.7638660863534722, + 0.7707187529126627, + 0.7776050951883239, + 0.7845251431493403, + 0.7914789266716237, + 0.7984664755387687, + 0.8054878194427022, + 0.8125429879843271, + 0.8196320106741564, + 0.8267549169329416, + 0.8339117360922947, + 0.841102497395304, + 0.8483272299971403, + 0.8555859629656606, + 0.8628787252820025, + 0.8702055458411739, + 0.8775664534526355, + 0.8849614768408772, + 0.89239064464599, + 0.8998539854242292, + 0.9073515276485736, + 0.9148832997092798, + 0.9224493299144275, + 0.9300496464904624, + 0.9376842775827321, + 0.9453532512560171, + 0.9530565954950551, + 0.9607943382050612, + 0.9685665072122436, + 0.9763731302643115, + 0.9842142350309797, + 0.9920898491044691, + 1.0, +]; + +pub const TO_REC_OETF_U8: [u32; 104] = [ + 0x00520004, 0x00550004, 0x00570004, 0x00590004, 0x005b0004, 0x005e0004, 0x00600004, 0x00620004, + 0x00640009, 0x00690009, 0x006d0009, 0x00720009, 0x00760009, 0x007b0009, 0x007f0009, 0x00840009, + 0x00880012, 0x00910012, 0x009a0012, 0x00a30012, 0x00ac0012, 0x00b50012, 0x00be0012, 0x00c70012, + 0x00d00024, 0x00e20024, 0x00f40024, 0x01060024, 0x01180024, 0x012a0024, 0x013c0024, 0x014d0024, + 0x015f0048, 0x01830048, 0x01a70048, 0x01cb0048, 0x01ef0048, 0x02130048, 0x02370048, 0x025a0048, + 0x027e008f, 0x02c6008f, 0x030e008f, 0x0355008f, 0x039d008f, 0x03e5008f, 0x042d008f, 0x0474008f, + 0x04bc011f, 0x054b011f, 0x05db011f, 0x066a011f, 0x06fa011f, 0x0789011f, 0x0819011f, 0x08a8011f, + 0x0938023e, 0x0a580235, 0x0b720217, 0x0c7e01fd, 0x0d7c01e6, 0x0e6f01d2, 0x0f5801c0, 0x103801b0, + 0x11120335, 0x12ac0304, 0x142e02db, 0x159b02b7, 0x16f60298, 0x1842027c, 0x19800264, 0x1ab2024e, + 0x1bdc0461, 0x1e0c041f, 0x201b03e6, 0x220e03b6, 0x23e9038b, 0x25ae0365, 0x27600344, 0x29020326, + 0x2a9a05fc, 0x2d9705a1, 0x30670554, 0x33100511, 0x359804d7, 0x380304a4, 0x3a550476, 0x3c90044d, + 0x3ebc082d, 0x42d107b1, 0x46a90747, 0x4a4c06ec, 0x4dc1069d, 0x510f0656, 0x543a0618, 0x574505e0, + 0x5a3e0b2b, 0x5fd20a81, 0x651109f1, 0x6a080975, 0x6ec20908, 0x734508a8, 0x77990853, 0x7bc20806, +]; diff --git a/palette/src/lib.rs b/palette/src/lib.rs index 88c13730d..50645662f 100644 --- a/palette/src/lib.rs +++ b/palette/src/lib.rs @@ -312,7 +312,7 @@ pub use oklab::{Oklab, Oklaba}; #[doc(inline)] pub use oklch::{Oklch, Oklcha}; #[doc(inline)] -pub use rgb::{GammaSrgb, GammaSrgba, LinSrgb, LinSrgba, Srgb, Srgba}; +pub use rgb::{GammaSrgb, GammaSrgba, LinRec2020, LinSrgb, LinSrgba, Rec2020, Rec709, Srgb, Srgba}; #[doc(inline)] pub use xyz::{Xyz, Xyza}; #[doc(inline)] diff --git a/palette/src/rgb.rs b/palette/src/rgb.rs index 7ace35d41..7c18101a1 100644 --- a/palette/src/rgb.rs +++ b/palette/src/rgb.rs @@ -133,6 +133,30 @@ pub type GammaSrgb = Rgb, T>; /// create a value and use it. pub type GammaSrgba = Rgba, T>; +/// Rec. 709. +/// +/// This standard has the same primaries as [`Srgb`], but uses the transfer +/// function detailed in ITU-R Recommendation BT.709. +/// +/// See [`Rgb`] for more details on how to create a value and use it. +pub type Rec709 = Rgb; + +/// Non-linear Rec. 2020, a wide color gamut RGB format. +/// +/// This is an RGB standard with a color gamut much wider than that of [`Srgb`]. +/// +/// See [`Rgb`] for more details on how to create a value and use it. +pub type Rec2020 = Rgb; + +/// Linear Rec. 2020. +/// +/// You probably want [`Rec2020`] if you are looking for an input or output format. +/// This is the linear version of Rec. 2020, which is what you would usually +/// convert to before working with the color. +/// +/// See [`Rgb`] for more details on how to create a value and use it. +pub type LinRec2020 = Rgb, T>; + /// An RGB space and a transfer function. pub trait RgbStandard { /// The RGB color space.