Skip to main content

figments_render/
gamma.rs

1use rgb::{Bgr, Grb, Rgb};
2use core::array;
3use core::ops::Index;
4
5#[cfg(feature="micromath")]
6use micromath::F32Ext;
7
8#[derive(Debug)]
9pub struct GammaCurve([u8; 256]);
10
11impl GammaCurve {
12    pub fn new(gamma: f32) -> Self {
13        Self(array::from_fn(|x| {
14            Self::gamma_for_value(x as u8, gamma)
15        }))
16    }
17
18    fn gamma_for_value(value: u8, gamma: f32) -> u8 {
19        ((value as f32 / 255f32).powf(gamma) * 255f32 + 0.5) as u8
20    }
21}
22
23impl Default for GammaCurve {
24    fn default() -> Self {
25        Self::new(1.0)
26    }
27}
28
29impl Index<usize> for GammaCurve {
30    type Output = u8;
31
32    fn index(&self, index: usize) -> &Self::Output {
33        &self.0[index]
34    }
35}
36
37pub trait WithGamma {
38    fn with_gamma(self, curve: &GammaCurve) -> Self;
39}
40
41impl WithGamma for Rgb<u8> {
42    fn with_gamma(self, curve: &GammaCurve)-> Self {
43        Rgb::new(curve[self.r as usize], curve[self.g as usize], curve[self.b as usize])
44    }
45}
46
47impl WithGamma for Grb<u8> {
48    fn with_gamma(self, curve: &GammaCurve) -> Self {
49        Grb::new_grb(curve[self.g as usize], curve[self.r as usize], curve[self.b as usize])
50    }
51}
52
53impl WithGamma for Bgr<u8> {
54    fn with_gamma(self, curve: &GammaCurve) -> Self {
55        Bgr::new_bgr(curve[self.b as usize], curve[self.g as usize], curve[self.r as usize])
56    }
57}
58
59impl<T: WithGamma + Copy, const SIZE: usize> WithGamma for [T; SIZE] {
60    fn with_gamma(self, curve: &GammaCurve) -> Self {
61        array::from_fn(|x| { self[x].with_gamma(curve) })
62    }
63}