use core::{marker::PhantomData, ops::Div};
use crate::{
luma::LumaStandard,
num::{One, Powf, Real},
rgb::{RgbSpace, RgbStandard},
};
use super::{FromLinear, IntoLinear};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Gamma<S, N: Number = F2p2>(PhantomData<(S, N)>);
impl<Sp, N> RgbStandard for Gamma<Sp, N>
where
Sp: RgbSpace,
N: Number,
{
type Space = Sp;
type TransferFn = GammaFn<N>;
}
impl<Wp, N> LumaStandard for Gamma<Wp, N>
where
N: Number,
{
type WhitePoint = Wp;
type TransferFn = GammaFn<N>;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct GammaFn<N: Number = F2p2>(PhantomData<N>);
impl<T, N> IntoLinear<T, T> for GammaFn<N>
where
T: Real + One + Powf + Div<Output = T>,
N: Number,
{
#[inline]
fn into_linear(x: T) -> T {
x.powf(T::one() / T::from_f64(N::VALUE))
}
}
impl<T, N> FromLinear<T, T> for GammaFn<N>
where
T: Real + Powf,
N: Number,
{
#[inline]
fn from_linear(x: T) -> T {
x.powf(T::from_f64(N::VALUE))
}
}
pub trait Number: 'static {
const VALUE: f64;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct F2p2;
impl Number for F2p2 {
const VALUE: f64 = 2.2;
}