#![allow(dead_code)]
pub const DISPLAY_P3_WHITE_XY: [f32; 2] = [0.3127, 0.3290];
#[derive(Debug, Clone, Copy)]
pub struct DisplayP3Primaries {
pub red: [f32; 2],
pub green: [f32; 2],
pub blue: [f32; 2],
}
impl Default for DisplayP3Primaries {
fn default() -> Self {
Self {
red: [0.680, 0.320],
green: [0.265, 0.690],
blue: [0.150, 0.060],
}
}
}
#[derive(Debug, Clone)]
pub struct DisplayP3Config {
pub primaries: DisplayP3Primaries,
pub white_point: [f32; 2],
pub use_srgb_transfer: bool,
}
impl Default for DisplayP3Config {
fn default() -> Self {
Self {
primaries: DisplayP3Primaries::default(),
white_point: DISPLAY_P3_WHITE_XY,
use_srgb_transfer: true,
}
}
}
pub fn gamma22_eotf(encoded: f32) -> f32 {
encoded.clamp(0.0, 1.0).powf(2.2)
}
pub fn gamma22_oetf(linear: f32) -> f32 {
linear.clamp(0.0, 1.0).powf(1.0 / 2.2)
}
pub fn export_display_p3_config(cfg: &DisplayP3Config) -> String {
format!(
"Display P3\nWhite: ({:.4}, {:.4})\nsRGB transfer: {}\nR: ({:.3}, {:.3})\nG: ({:.3}, {:.3})\nB: ({:.3}, {:.3})\n",
cfg.white_point[0], cfg.white_point[1],
cfg.use_srgb_transfer,
cfg.primaries.red[0], cfg.primaries.red[1],
cfg.primaries.green[0], cfg.primaries.green[1],
cfg.primaries.blue[0], cfg.primaries.blue[1],
)
}
pub fn validate_display_p3_config(cfg: &DisplayP3Config) -> bool {
cfg.white_point[0] > 0.0 && cfg.white_point[1] > 0.0
}
pub fn display_p3_to_linear(rgb: [f32; 3]) -> [f32; 3] {
[
gamma22_eotf(rgb[0]),
gamma22_eotf(rgb[1]),
gamma22_eotf(rgb[2]),
]
}
pub fn is_wider_than_srgb() -> bool {
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gamma22_eotf_zero() {
assert_eq!(gamma22_eotf(0.0), 0.0);
}
#[test]
fn test_gamma22_eotf_one() {
assert!((gamma22_eotf(1.0) - 1.0).abs() < f32::EPSILON);
}
#[test]
fn test_gamma22_oetf_one() {
assert!((gamma22_oetf(1.0) - 1.0).abs() < f32::EPSILON);
}
#[test]
fn test_roundtrip() {
let v = 0.6f32;
assert!((gamma22_eotf(gamma22_oetf(v)) - v).abs() < 0.001);
}
#[test]
fn test_export_contains_display_p3() {
assert!(export_display_p3_config(&DisplayP3Config::default()).contains("Display P3"));
}
#[test]
fn test_validate_default_config() {
assert!(validate_display_p3_config(&DisplayP3Config::default()));
}
#[test]
fn test_validate_zero_white_point_fails() {
let cfg = DisplayP3Config {
white_point: [0.0, 0.0],
..Default::default()
};
assert!(!validate_display_p3_config(&cfg));
}
#[test]
fn test_display_p3_to_linear_length() {
assert_eq!(display_p3_to_linear([0.5, 0.5, 0.5]).len(), 3);
}
#[test]
fn test_is_wider_than_srgb() {
assert!(is_wider_than_srgb());
}
#[test]
fn test_default_uses_srgb_transfer() {
assert!(DisplayP3Config::default().use_srgb_transfer);
}
}