jay-compositor 1.15.0

The Jay compositor
use crate::cmm::cmm_eotf::Eotf;
use crate::cmm::cmm_luminance::Luminance;
use crate::cmm::cmm_manager::ColorManager;
use crate::cmm::cmm_primaries::Primaries;

mod matrices {
    use crate::cmm::cmm_primaries::Primaries;
    use crate::utils::ordered_float::F64;

    fn check(primaries: Primaries, expected: [[f64; 4]; 3]) {
        let (ltg, gtl) = primaries.matrices();
        println!("{ltg:#?}");
        assert!((ltg.0[0][0].0 - expected[0][0]).abs() < 0.001);
        assert!((ltg.0[0][1].0 - expected[0][1]).abs() < 0.001);
        assert!((ltg.0[0][2].0 - expected[0][2]).abs() < 0.001);
        assert!((ltg.0[0][3].0 - expected[0][3]).abs() < 0.001);
        assert!((ltg.0[1][0].0 - expected[1][0]).abs() < 0.001);
        assert!((ltg.0[1][1].0 - expected[1][1]).abs() < 0.001);
        assert!((ltg.0[1][2].0 - expected[1][2]).abs() < 0.001);
        assert!((ltg.0[1][3].0 - expected[1][3]).abs() < 0.001);
        assert!((ltg.0[2][0].0 - expected[2][0]).abs() < 0.001);
        assert!((ltg.0[2][1].0 - expected[2][1]).abs() < 0.001);
        assert!((ltg.0[2][2].0 - expected[2][2]).abs() < 0.001);
        assert!((ltg.0[2][3].0 - expected[2][3]).abs() < 0.001);
        let roundtrip = gtl * ltg;
        assert!((roundtrip.0[0][0].0 - 1.0).abs() < 0.001);
        assert!((roundtrip.0[0][1].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[0][2].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[0][3].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[1][0].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[1][1].0 - 1.0).abs() < 0.001);
        assert!((roundtrip.0[1][2].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[1][3].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[2][0].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[2][1].0 - 0.0).abs() < 0.001);
        assert!((roundtrip.0[2][2].0 - 1.0).abs() < 0.001);
        assert!((roundtrip.0[2][3].0 - 0.0).abs() < 0.001);
    }

    #[test]
    fn srgb() {
        check(
            Primaries::SRGB,
            [
                [0.4124564, 0.3575761, 0.1804375, 0.0],
                [0.2126729, 0.7151522, 0.0721750, 0.0],
                [0.0193339, 0.1191920, 0.9503041, 0.0],
            ],
        );
    }

    #[test]
    fn cie1931_xyz() {
        check(
            Primaries::CIE1931_XYZ,
            [
                [1.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
            ],
        );
    }

    #[test]
    fn adobe_rgb() {
        check(
            Primaries::ADOBE_RGB,
            [
                [0.5767309, 0.1855540, 0.1881852, 0.0],
                [0.2973769, 0.6273491, 0.0752741, 0.0],
                [0.0270343, 0.0706872, 0.9911085, 0.0],
            ],
        );
    }

    #[test]
    fn apple_rgb() {
        check(
            Primaries {
                r: (F64(0.625), F64(0.34)),
                g: (F64(0.28), F64(0.595)),
                b: (F64(0.155), F64(0.07)),
                wp: (F64(0.31271), F64(0.32902)),
            },
            [
                [0.4497288, 0.3162486, 0.1844926, 0.0],
                [0.2446525, 0.6720283, 0.0833192, 0.0],
                [0.0251848, 0.1411824, 0.9224628, 0.0],
            ],
        );
    }

    #[test]
    fn bt2020() {
        check(
            Primaries::BT2020,
            [
                [0.636958, 0.144617, 0.168881, 0.0],
                [0.262700, 0.677998, 0.059302, 0.0],
                [0.000000, 0.028073, 1.060985, 0.0],
            ],
        );
    }

    #[test]
    fn pal() {
        check(
            Primaries::PAL,
            [
                [0.4306190, 0.3415419, 0.1783091, 0.0],
                [0.2220379, 0.7066384, 0.0713236, 0.0],
                [0.0201853, 0.1295504, 0.9390944, 0.0],
            ],
        );
    }

    #[test]
    fn dci_p3() {
        check(
            Primaries::DCI_P3,
            [
                [0.445170, 0.277134, 0.172283, 0.0],
                [0.209492, 0.721595, 0.068913, 0.0],
                [-0.000000, 0.047061, 0.907355, 0.0],
            ],
        );
    }

    #[test]
    fn display_p3() {
        check(
            Primaries::DISPLAY_P3,
            [
                [0.486571, 0.265668, 0.198217, 0.0],
                [0.228975, 0.691739, 0.079287, 0.0],
                [-0.000000, 0.045113, 1.043944, 0.0],
            ],
        );
    }
}

mod transforms {
    use crate::cmm::cmm_eotf::Eotf;
    use crate::cmm::cmm_luminance::Luminance;
    use crate::cmm::cmm_manager::ColorManager;
    use crate::cmm::cmm_primaries::Primaries;
    use crate::cmm::cmm_render_intent::RenderIntent;

    fn check(p1: Primaries, p2: Primaries, expected: [[f64; 4]; 3]) {
        let manager = ColorManager::new();
        let d = |p| {
            manager.get_description(
                None,
                p,
                Luminance::SRGB,
                Eotf::Linear,
                p,
                Luminance::SRGB.to_target(),
                None,
                None,
            )
        };
        let d1 = d(p1);
        let d2 = d(p2);
        let m = d1
            .linear
            .color_transform(&d2.linear, RenderIntent::Perceptual);
        println!("{m:#?}");
        assert!((m.0[0][0].0 - expected[0][0]).abs() < 0.001);
        assert!((m.0[0][1].0 - expected[0][1]).abs() < 0.001);
        assert!((m.0[0][2].0 - expected[0][2]).abs() < 0.001);
        assert!((m.0[0][3].0 - expected[0][3]).abs() < 0.001);
        assert!((m.0[1][0].0 - expected[1][0]).abs() < 0.001);
        assert!((m.0[1][1].0 - expected[1][1]).abs() < 0.001);
        assert!((m.0[1][2].0 - expected[1][2]).abs() < 0.001);
        assert!((m.0[1][3].0 - expected[1][3]).abs() < 0.001);
        assert!((m.0[2][0].0 - expected[2][0]).abs() < 0.001);
        assert!((m.0[2][1].0 - expected[2][1]).abs() < 0.001);
        assert!((m.0[2][2].0 - expected[2][2]).abs() < 0.001);
        assert!((m.0[2][3].0 - expected[2][3]).abs() < 0.001);
    }

    #[test]
    fn srgb_to_bt2020() {
        check(
            Primaries::SRGB,
            Primaries::BT2020,
            [
                [0.627404, 0.329283, 0.043313, 0.0],
                [0.069097, 0.919540, 0.011362, 0.0],
                [0.016391, 0.088013, 0.895595, 0.0],
            ],
        );
    }

    #[test]
    fn bt2020_to_srgb() {
        check(
            Primaries::BT2020,
            Primaries::SRGB,
            [
                [1.660491, -0.587641, -0.072850, 0.0],
                [-0.124550, 1.132900, -0.008349, 0.0],
                [-0.018151, -0.100579, 1.118730, 0.0],
            ],
        );
    }

    #[test]
    fn srgb_to_dci_p3() {
        check(
            Primaries::SRGB,
            Primaries::DCI_P3,
            [
                [0.868580, 0.128919, 0.002501, 0.0],
                [0.034540, 0.961811, 0.003648, 0.0],
                [0.016771, 0.071040, 0.912189, 0.0],
            ],
        );
    }
}

#[test]
fn target_contained() {
    let cm = ColorManager::new();
    assert!(cm.srgb_gamma22().linear.target_contained_in_primary());
    assert!(!cm.windows_scrgb().linear.target_contained_in_primary());
    assert!(cm.windows_bt2100().linear.target_contained_in_primary());

    let get_description =
        |p, l, tp, tl| cm.get_description(None, p, l, Eotf::Linear, tp, tl, None, None);

    {
        let mut srgb_modified = Primaries::SRGB;
        srgb_modified.r.0.0 += 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            srgb_modified,
            Luminance::SRGB.to_target(),
        );
        assert!(!desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Primaries::SRGB;
        srgb_modified.r.0.0 -= 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            srgb_modified,
            Luminance::SRGB.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
    }

    {
        let desc = get_description(
            Primaries::DCI_P3,
            Luminance::SRGB,
            Primaries::SRGB,
            Luminance::SRGB.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Primaries::SRGB;
        srgb_modified.r = Primaries::BT2020.r;
        let desc = get_description(
            Primaries::DCI_P3,
            Luminance::SRGB,
            srgb_modified,
            Luminance::SRGB.to_target(),
        );
        assert!(!desc.linear.target_contained_in_primary());
    }

    {
        let mut bt2020_modified = Primaries::BT2020;
        bt2020_modified.r.1.0 *= -1.0;
        bt2020_modified.g.1.0 *= -1.0;
        bt2020_modified.b.1.0 *= -1.0;
        let mut srgb_modified = Primaries::SRGB;
        srgb_modified.r.1.0 *= -1.0;
        srgb_modified.g.1.0 *= -1.0;
        srgb_modified.b.1.0 *= -1.0;
        let desc = get_description(
            Primaries::BT2020,
            Luminance::SRGB,
            Primaries::SRGB,
            Luminance::SRGB.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
        let desc = get_description(
            bt2020_modified,
            Luminance::SRGB,
            srgb_modified,
            Luminance::SRGB.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Luminance::SRGB;
        srgb_modified.min.0 -= 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            Primaries::SRGB,
            srgb_modified.to_target(),
        );
        assert!(!desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Luminance::SRGB;
        srgb_modified.min.0 += 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            Primaries::SRGB,
            srgb_modified.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Luminance::SRGB;
        srgb_modified.max.0 -= 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            Primaries::SRGB,
            srgb_modified.to_target(),
        );
        assert!(desc.linear.target_contained_in_primary());
    }

    {
        let mut srgb_modified = Luminance::SRGB;
        srgb_modified.max.0 += 0.001;
        let desc = get_description(
            Primaries::SRGB,
            Luminance::SRGB,
            Primaries::SRGB,
            srgb_modified.to_target(),
        );
        assert!(!desc.linear.target_contained_in_primary());
    }
}