Skip to content

Commit

Permalink
Improve PQ OETF accuracy
Browse files Browse the repository at this point in the history
JzAzBz and ICtCp succeed nan checks on f64 now
  • Loading branch information
Beinsezii committed Jun 26, 2024
1 parent 4f75dd7 commit 37f7d61
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod tests;

use core::cmp::PartialOrd;
use core::ffi::{c_char, CStr};
use core::fmt::Display;
use core::ops::{Add, Div, Mul, Neg, Rem, Sub};

// DType {{{
Expand Down Expand Up @@ -72,6 +73,7 @@ pub trait DType:
+ Rem<Output = Self>
+ Sub<Output = Self>
+ PartialOrd
+ Display
+ FromF32
{
fn powi(self, rhs: i32) -> Self;
Expand Down Expand Up @@ -395,7 +397,7 @@ fn pq_oetf_common<T: DType>(f: T, m2: T) -> T {
let numerator: T = T::ff32(PQEOTF_C2).fma(y_pow_m1, PQEOTF_C1.to_dt());
let denominator: T = T::ff32(PQEOTF_C3).fma(y_pow_m1, 1.0.to_dt());

(numerator / denominator).powf(m2)
(numerator / denominator).spowf(m2)
}

/// Dolby Perceptual Quantizer Electro-Optical Transfer Function primarily used for ICtCP
Expand Down Expand Up @@ -544,7 +546,7 @@ impl TryFrom<&str> for Space {
}
}

impl core::fmt::Display for Space {
impl Display for Space {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::write(
f,
Expand Down
36 changes: 20 additions & 16 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ fn individual() {
("CIELAB->XYZ", CIELAB, XYZ, cielab_to_xyz),
("XYZ->OKLAB", XYZ, OKLAB, xyz_to_oklab),
("OKLAB->XYZ", OKLAB, XYZ, oklab_to_xyz),
//("XYZ->JZAZBZ", XYZ, JZAZBZ, xyz_to_jzazbz)
//("XYZ->JZAZBZ", XYZ, JZAZBZ, xyz_to_jzazbz),
("JZAZBZ->XYZ", JZAZBZ, XYZ, jzazbz_to_xyz),
("CIELAB->CIELCH", CIELAB, CIELCH, lab_to_lch),
("CIELCH->CIELAB", CIELCH, CIELAB, lch_to_lab),
Expand Down Expand Up @@ -426,26 +426,30 @@ fn nan_checks() {
let it = [1e+3, -1e+3, 1e-3, -1e-3];
// do these at f32 to faster approach bounds
let fns: &[(&'static str, fn(&mut [f32; 3]))] = &[
("hsv_forwards", srgb_to_hsv),
("hsv_backwards", hsv_to_srgb),
("lrgb_forwards", srgb_to_lrgb),
("lrgb_backwards", lrgb_to_srgb),
("xyz_forwards", lrgb_to_xyz),
("xyz_backwards", xyz_to_lrgb),
("lab_forwards", xyz_to_cielab),
("lab_backwards", cielab_to_xyz),
("lch_forwards", lab_to_lch),
("lch_backwards", lch_to_lab),
("oklab_forwards", xyz_to_oklab),
("oklab_backwards", oklab_to_xyz),
//("jzazbz_forwards", xyz_to_jzazbz), // ugh
("jzazbz_backwards", jzazbz_to_xyz),
("srgb_to_hsv", srgb_to_hsv),
("hsv_to_srgb", hsv_to_srgb),
("srgb_to_lrgb", srgb_to_lrgb),
("lrgb_to_srgb", lrgb_to_srgb),
("lrgb_to_xyz", lrgb_to_xyz),
("xyz_to_lrgb", xyz_to_lrgb),
("xyz_to_cielab", xyz_to_cielab),
("cielab_to_xyz", cielab_to_xyz),
("lab_to_lch", lab_to_lch),
("lch_to_lab", lch_to_lab),
("xyz_to_oklab", xyz_to_oklab),
("oklab_to_xyz", oklab_to_xyz),
// fails hard in the PQ function with (N/D)^P
// Succeeds in F64 but graphics is almost always run in F32
//("xyz_to_jzazbz", xyz_to_jzazbz),
("jzazbz_to_xyz", jzazbz_to_xyz),
("_lrgb_to_ictcp", _lrgb_to_ictcp),
("_ictcp_to_lrgb", _ictcp_to_lrgb),
];
for (label, func) in fns {
for a in it.iter() {
for b in it.iter() {
for c in it.iter() {
let from: [f32; 3] = [*a, *b, *c];
let from = [*a, *b, *c];
let mut to = from;
func(&mut to);
if to.iter().any(|c| !c.is_finite()) {
Expand Down

0 comments on commit 37f7d61

Please sign in to comment.