e
Diffstat (limited to 'src/color.rs')
-rwxr-xr-xsrc/color.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/color.rs b/src/color.rs
new file mode 100755
index 0000000..96efe3b
--- /dev/null
+++ b/src/color.rs
@@ -0,0 +1,109 @@
+use crate::StackBlurrable;
+use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
+
+mod serial;
+mod simd;
+
+pub use serial::BlurU32;
+pub use simd::u32xN;
+
+use std::simd::{LaneCount, Simd, SupportedLaneCount};
+
+#[repr(transparent)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
+pub struct Argb<T: StackBlurrable>([T; 4]);
+
+impl From<u32> for Argb<BlurU32> {
+ fn from(argb: u32) -> Self {
+ let [a, r, g, b] = argb.to_be_bytes();
+ let cvt = |i| BlurU32(i as u32);
+ Self([cvt(a), cvt(r), cvt(g), cvt(b)])
+ }
+}
+
+impl From<Argb<BlurU32>> for u32 {
+ fn from(Argb([a, r, g, b]): Argb<BlurU32>) -> Self {
+ let cvt = |i: BlurU32| i.0 as u8;
+ u32::from_be_bytes([cvt(a), cvt(r), cvt(g), cvt(b)])
+ }
+}
+
+impl<const N: usize> From<[u32; N]> for Argb<u32xN<N>>
+where
+ LaneCount<N>: SupportedLaneCount,
+{
+ fn from(values: [u32; N]) -> Self {
+ let arrs: [[u8; 4]; N] = values.map(u32::to_be_bytes);
+ Self([
+ u32xN(Simd::from_array(arrs.map(|a| a[0] as u32))),
+ u32xN(Simd::from_array(arrs.map(|a| a[1] as u32))),
+ u32xN(Simd::from_array(arrs.map(|a| a[2] as u32))),
+ u32xN(Simd::from_array(arrs.map(|a| a[3] as u32))),
+ ])
+ }
+}
+
+impl<const N: usize> From<Argb<u32xN<N>>> for [u32; N]
+where
+ LaneCount<N>: SupportedLaneCount,
+{
+ fn from(value: Argb<u32xN<N>>) -> Self {
+ let [a, r, g, b] = value.0.map(|i| i.0.to_array());
+ std::array::from_fn(|i| u32::from_be_bytes([a[i], r[i], g[i], b[i]].map(|x| x as u8)))
+ }
+}
+
+impl<T: StackBlurrable> Add for Argb<T> {
+ type Output = Self;
+
+ fn add(mut self, rhs: Self) -> Self::Output {
+ self += rhs;
+ self
+ }
+}
+
+impl<T: StackBlurrable> Sub for Argb<T> {
+ type Output = Self;
+
+ fn sub(mut self, rhs: Self) -> Self::Output {
+ self -= rhs;
+ self
+ }
+}
+
+impl<T: StackBlurrable> AddAssign for Argb<T> {
+ fn add_assign(&mut self, rhs: Self) {
+ let [a, r, g, b] = rhs.0;
+ self.0[0] += a;
+ self.0[1] += r;
+ self.0[2] += g;
+ self.0[3] += b;
+ }
+}
+
+impl<T: StackBlurrable> SubAssign for Argb<T> {
+ fn sub_assign(&mut self, rhs: Self) {
+ let [a, r, g, b] = rhs.0;
+ self.0[0] -= a;
+ self.0[1] -= r;
+ self.0[2] -= g;
+ self.0[3] -= b;
+ }
+}
+
+impl<T: StackBlurrable> Mul<usize> for Argb<T> {
+ type Output = Self;
+
+ fn mul(self, rhs: usize) -> Self::Output {
+ let [a, r, g, b] = self.0;
+ Self([a * rhs, r * rhs, g * rhs, b * rhs])
+ }
+}
+
+impl<T: StackBlurrable> Div<usize> for Argb<T> {
+ type Output = Self;
+ fn div(self, rhs: usize) -> Self::Output {
+ let [a, r, g, b] = self.0;
+ Self([a / rhs, r / rhs, g / rhs, b / rhs])
+ }
+}