use std::{f32, ops::Mul};
const A: usize = 0;
const R: usize = 1;
const G: usize = 2;
const B: usize = 3;
const EPSILON: f32 = f32::EPSILON * 100f32;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Pel(u32);
impl Pel {
pub fn a(self) -> u8 {
self.0.to_le_bytes()[A]
}
pub fn r(self) -> u8 {
self.0.to_le_bytes()[R]
}
pub fn g(self) -> u8 {
self.0.to_le_bytes()[G]
}
pub fn b(self) -> u8 {
self.0.to_le_bytes()[B]
}
}
impl Default for Pel {
fn default() -> Self {
[255u8, 0, 0, 0].into()
}
}
impl From<u32> for Pel {
fn from(color: u32) -> Self {
Self(color)
}
}
impl From<Pel> for u32 {
fn from(pel: Pel) -> Self {
pel.0
}
}
impl From<[u8; 4]> for Pel {
fn from(bytes: [u8; 4]) -> Self {
Self(u32::from_le_bytes(bytes))
}
}
impl From<Pel> for [u8; 4] {
fn from(pel: Pel) -> Self {
pel.0.to_le_bytes()
}
}
impl From<[f32; 4]> for Pel {
fn from(floats: [f32; 4]) -> Self {
Self::from([
floats[A].mul(256f32 - EPSILON) as u8,
floats[R].mul(256f32 - EPSILON) as u8,
floats[G].mul(256f32 - EPSILON) as u8,
floats[B].mul(256f32 - EPSILON) as u8,
])
}
}
impl From<Pel> for [f32; 4] {
fn from(pel: Pel) -> Self {
let bytes: [u8; 4] = pel.into();
[
bytes[A] as f32 / 255f32,
bytes[R] as f32 / 255f32,
bytes[G] as f32 / 255f32,
bytes[B] as f32 / 255f32,
]
}
}