From a06ce7a64ff48ba9b91de122eb0579a88e8dae28 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sun, 11 Aug 2024 13:02:04 -0700 Subject: [PATCH] Custom implementation to avoid GammaFn bug --- palette/src/encoding/adobe.rs | 56 ++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/palette/src/encoding/adobe.rs b/palette/src/encoding/adobe.rs index e445ba814..62960225e 100644 --- a/palette/src/encoding/adobe.rs +++ b/palette/src/encoding/adobe.rs @@ -1,14 +1,15 @@ //! The Adobe RGB (1998) standard. use crate::{ - encoding::gamma::GammaFn, luma::LumaStandard, - num::Real, + num::{Powf, Real}, rgb::{Primaries, RgbSpace, RgbStandard}, white_point::{Any, D65}, Mat3, Yxy, }; +use super::{FromLinear, IntoLinear}; + /// The Adobe RGB (1998) (a.k.a. opRGB) color space and standard. /// /// This color space was designed to encompass most colors achievable by CMYK @@ -74,12 +75,30 @@ impl RgbSpace for AdobeRgb { impl RgbStandard for AdobeRgb { type Space = AdobeRgb; - type TransferFn = GammaFn; + type TransferFn = AdobeRgb; } impl LumaStandard for AdobeRgb { type WhitePoint = D65; - type TransferFn = GammaFn; + type TransferFn = AdobeRgb; +} + +impl IntoLinear for AdobeRgb +where + T: Real + Powf, +{ + fn into_linear(encoded: T) -> T { + encoded.powf(T::from_f64(563.0 / 256.0)) + } +} + +impl FromLinear for AdobeRgb +where + T: Real + Powf, +{ + fn from_linear(linear: T) -> T { + linear.powf(T::from_f64(256.0 / 563.0)) + } } #[cfg(test)] @@ -106,4 +125,33 @@ mod test { assert_relative_eq!(dynamic[..], constant[..], epsilon = 0.0000001); } } + + #[cfg(feature = "approx")] + mod transfer { + use crate::encoding::{AdobeRgb, FromLinear, IntoLinear}; + + #[test] + fn lin_to_enc_to_lin() { + for i in 0..=100 { + let linear = i as f64 / 100.0; + let encoded: f64 = AdobeRgb::from_linear(linear); + assert_relative_eq!(linear, AdobeRgb::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 = AdobeRgb::into_linear(encoded); + assert_relative_eq!(encoded, AdobeRgb::from_linear(linear), epsilon = 0.0000001); + } + } + + #[test] + fn correct_values() { + assert_relative_eq!(AdobeRgb::from_linear(0.5), 0.72965838, epsilon = 0.0000001); + assert_relative_eq!(AdobeRgb::into_linear(0.5), 0.21775552, epsilon = 0.0000001); + } + } }