use std::ops::{Add, Sub, Mul, Div, Neg, AddAssign, SubAssign, MulAssign};
#[derive(Debug, Default, Clone, PartialEq)]
pub struct RGB(pub f64, pub f64, pub f64);
impl RGB {
const ALMOST_BYTE_MAX: f64 = 256.0 - f64::EPSILON;
pub fn new(r: f64, g: f64, b: f64) -> Self {
RGB(r, g, b)
}
pub fn r(&self) -> f64 {
self.0
}
pub fn g(&self) -> f64 {
self.1
}
pub fn b(&self) -> f64 {
self.2
}
pub fn correct_gamma(&self, gamma: f64) -> RGB {
let one_over_gamma = 1.0 / gamma;
Self(self.0.powf(one_over_gamma), self.1.powf(one_over_gamma), self.2.powf(one_over_gamma))
}
pub fn as_bytes(&self) -> [u8; 3] {
[(self.0 * Self::ALMOST_BYTE_MAX) as u8, (self.1 * Self::ALMOST_BYTE_MAX) as u8, (self.2 * Self::ALMOST_BYTE_MAX) as u8]
}
}
impl Add<f64> for RGB {
type Output = Self;
fn add(self, scalar: f64) -> Self::Output {
Self(self.0 + scalar, self.1 + scalar, self.2 + scalar)
}
}
impl Sub<f64> for RGB {
type Output = Self;
fn sub(self, scalar: f64) -> Self::Output {
self + (-scalar)
}
}
impl Mul<f64> for RGB {
type Output = Self;
fn mul(self, scalar: f64) -> Self::Output {
Self(self.0 * scalar, self.1 * scalar, self.2 * scalar)
}
}
impl Div<f64> for RGB {
type Output = Self;
fn div(self, scalar: f64) -> Self::Output {
self * (1.0 / scalar)
}
}
impl Add<RGB> for RGB {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
}
}
impl Sub<RGB> for RGB {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
self + (-rhs)
}
}
impl Mul<RGB> for RGB {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0, self.1 * rhs.1, self.2 * rhs.2)
}
}
impl Neg for RGB {
type Output = Self;
fn neg(self) -> Self::Output {
Self(-self.0, -self.1, -self.2)
}
}
impl AddAssign<RGB> for RGB {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
self.1 += rhs.1;
self.2 += rhs.2;
}
}
impl SubAssign<RGB> for RGB {
fn sub_assign(&mut self, rhs: Self) {
*self += -rhs;
}
}
impl MulAssign<RGB> for RGB {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
self.1 *= rhs.1;
self.2 *= rhs.2;
}
}