#![forbid(unsafe_code)]
#[inline]
pub(crate) fn srgb_to_linear(gamma: f32) -> f32 {
if gamma < 0f32 {
0f32
} else if gamma < 12.92f32 * 0.003_041_282_5_f32 {
gamma * (1f32 / 12.92f32)
} else if gamma < 1.0f32 {
((gamma + 0.055_010_717_f32) / 1.055_010_7_f32).powf(2.4f32)
} else {
1.0f32
}
}
#[inline]
pub(crate) fn srgb_from_linear(linear: f32) -> f32 {
if linear < 0.0f32 {
0.0f32
} else if linear < 0.003_041_282_5_f32 {
linear * 12.92f32
} else if linear < 1.0f32 {
1.055_010_7_f32 * linear.powf(1.0f32 / 2.4f32) - 0.055_010_717_f32
} else {
1.0f32
}
}
#[inline]
pub(crate) fn rec709_to_linear(gamma: f32) -> f32 {
if gamma < 0.0f32 {
0.0f32
} else if gamma < 4.5f32 * 0.018_053_97_f32 {
gamma * (1f32 / 4.5f32)
} else if gamma < 1.0f32 {
((gamma + 0.099_296_82_f32) / 1.099_296_8_f32).powf(1.0f32 / 0.45f32)
} else {
1.0f32
}
}
#[inline]
pub(crate) fn rec709_from_linear(linear: f32) -> f32 {
if linear < 0.0f32 {
0.0f32
} else if linear < 0.018_053_97_f32 {
linear * 4.5f32
} else if linear < 1.0f32 {
1.099_296_8_f32 * linear.powf(0.45f32) - 0.099_296_82_f32
} else {
1.0f32
}
}
#[inline(always)]
pub(crate) fn pure_gamma_function(x: f32, gamma: f32) -> f32 {
if x <= 0f32 {
0f32
} else if x >= 1f32 {
1f32
} else {
x.powf(gamma)
}
}
#[inline]
pub(crate) fn gamma2p2_from_linear(linear: f32) -> f32 {
pure_gamma_function(linear, 1f32 / 2.2f32)
}
#[inline]
pub(crate) fn gamma2p2_to_linear(gamma: f32) -> f32 {
pure_gamma_function(gamma, 2.2f32)
}
#[inline]
pub(crate) fn gamma2p8_from_linear(linear: f32) -> f32 {
pure_gamma_function(linear, 1f32 / 2.8f32)
}
#[inline]
pub(crate) fn gamma2p8_to_linear(gamma: f32) -> f32 {
pure_gamma_function(gamma, 2.8f32)
}
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum SharpYuvGammaTransfer {
Srgb,
Rec709,
Gamma2p2,
Gamma2p8,
}
impl From<u8> for SharpYuvGammaTransfer {
fn from(value: u8) -> Self {
match value {
0 => SharpYuvGammaTransfer::Srgb,
1 => SharpYuvGammaTransfer::Rec709,
2 => SharpYuvGammaTransfer::Gamma2p2,
3 => SharpYuvGammaTransfer::Gamma2p8,
_ => SharpYuvGammaTransfer::Srgb,
}
}
}
impl SharpYuvGammaTransfer {
#[inline]
pub fn linearize(&self, value: f32) -> f32 {
match self {
SharpYuvGammaTransfer::Srgb => srgb_to_linear(value),
SharpYuvGammaTransfer::Rec709 => rec709_to_linear(value),
SharpYuvGammaTransfer::Gamma2p2 => gamma2p2_to_linear(value),
SharpYuvGammaTransfer::Gamma2p8 => gamma2p8_to_linear(value),
}
}
#[inline]
pub fn gamma(&self, value: f32) -> f32 {
match self {
SharpYuvGammaTransfer::Srgb => srgb_from_linear(value),
SharpYuvGammaTransfer::Rec709 => rec709_from_linear(value),
SharpYuvGammaTransfer::Gamma2p2 => gamma2p2_from_linear(value),
SharpYuvGammaTransfer::Gamma2p8 => gamma2p8_from_linear(value),
}
}
}