Compare commits

..

2 commits

Author SHA1 Message Date
Bruno BELANYI 0cfd9ee81d library: core: linearcolor: gamma correct on output 2020-03-26 23:43:38 +01:00
Bruno BELANYI 88478ebecf library: core: linearcolor: fix must_use attributes 2020-03-26 23:43:22 +01:00

View file

@ -29,6 +29,8 @@ pub struct LinearColor {
pub b: f32, pub b: f32,
} }
const GAMMA: f32 = 2.2;
impl LinearColor { impl LinearColor {
/// Creates the color black. /// Creates the color black.
/// ///
@ -49,6 +51,7 @@ impl LinearColor {
/// } /// }
/// ); /// );
/// ``` /// ```
#[must_use]
pub fn black() -> Self { pub fn black() -> Self {
LinearColor { LinearColor {
r: 0., r: 0.,
@ -66,11 +69,11 @@ impl LinearColor {
/// # /// #
/// let color = LinearColor::new(1.0, 0.0, 0.0); // bright red! /// let color = LinearColor::new(1.0, 0.0, 0.0); // bright red!
/// ``` /// ```
#[must_use]
pub fn new(r: f32, g: f32, b: f32) -> Self { pub fn new(r: f32, g: f32, b: f32) -> Self {
LinearColor { r, g, b } LinearColor { r, g, b }
} }
#[must_use]
/// Clamps the color's RGB components between 0.0 and 1.0. /// Clamps the color's RGB components between 0.0 and 1.0.
/// ///
/// # Examples /// # Examples
@ -81,6 +84,7 @@ impl LinearColor {
/// let color = LinearColor::new(1.5, -1.0, 0.5); /// let color = LinearColor::new(1.5, -1.0, 0.5);
/// assert_eq!(color.clamp(), LinearColor::new(1.0, 0.0, 0.5)) /// assert_eq!(color.clamp(), LinearColor::new(1.0, 0.0, 0.5))
/// ``` /// ```
#[must_use]
pub fn clamp(self) -> Self { pub fn clamp(self) -> Self {
fn clamp(v: f32) -> f32 { fn clamp(v: f32) -> f32 {
if v > 1. { if v > 1. {
@ -93,6 +97,26 @@ impl LinearColor {
}; };
LinearColor::new(clamp(self.r), clamp(self.g), clamp(self.b)) LinearColor::new(clamp(self.r), clamp(self.g), clamp(self.b))
} }
/// Encode the linear color into the gamma corrected space, as expected by most picture
/// formats.
#[must_use]
pub fn gamma_encode(self) -> Self {
fn gamma(val: f32) -> f32 {
val.powf(1.0 / GAMMA)
};
LinearColor::new(gamma(self.r), gamma(self.g), gamma(self.b))
}
/// Decode the linear color from the gamma corrected space, which is used in most picture
/// formats.
#[must_use]
pub fn gamma_decode(self) -> Self {
fn gamma(val: f32) -> f32 {
val.powf(GAMMA)
};
LinearColor::new(gamma(self.r), gamma(self.g), gamma(self.b))
}
} }
impl Default for LinearColor { impl Default for LinearColor {
@ -138,8 +162,8 @@ impl DivAssign for LinearColor {
} }
impl From<LinearColor> for image::Rgb<u8> { impl From<LinearColor> for image::Rgb<u8> {
fn from(mut color: LinearColor) -> Self { fn from(color: LinearColor) -> Self {
color = color.clamp(); let color = color.clamp().gamma_encode();
image::Rgb([ image::Rgb([
(color.r * 255.) as u8, (color.r * 255.) as u8,
(color.g * 255.) as u8, (color.g * 255.) as u8,