mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 10:28:21 -06:00
use atools
This commit is contained in:
parent
05f0d3d10d
commit
72be3fe0b0
|
@ -24,6 +24,7 @@ minifb = { version = "0.25.0", default-features = false, features = [
|
||||||
"wayland",
|
"wayland",
|
||||||
], optional = true }
|
], optional = true }
|
||||||
wgpu = { version = "0.19.1", default-features = false, optional = true }
|
wgpu = { version = "0.19.1", default-features = false, optional = true }
|
||||||
|
atools = "0.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
iai = { git = "https://github.com/bend-n/iai.git" }
|
iai = { git = "https://github.com/bend-n/iai.git" }
|
||||||
|
|
|
@ -109,7 +109,7 @@ trait CopyWithinUnchecked {
|
||||||
///
|
///
|
||||||
/// panicless version of [`[T]::copy_within`](`slice::copy_within`), where the slices cant overlap. this uses `memcpy`.
|
/// panicless version of [`[T]::copy_within`](`slice::copy_within`), where the slices cant overlap. this uses `memcpy`.
|
||||||
/// your slices must be in bounds.
|
/// your slices must be in bounds.
|
||||||
/// this isnt a public function, so im not going to say exactly what "in bounds" meeans.
|
/// this isnt a public function, so im not going to say exactly what "in bounds" means.
|
||||||
unsafe fn copy_within_unchecked(&mut self, src: Range<usize>, dest: usize);
|
unsafe fn copy_within_unchecked(&mut self, src: Range<usize>, dest: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! module for pixel blending ops
|
//! module for pixel blending ops
|
||||||
use super::{convert::PFrom, unfloat, Floatify, PMap, Trunc, Unfloatify};
|
use super::{convert::PFrom, unfloat, Floatify, Unfloatify};
|
||||||
|
use atools::prelude::*;
|
||||||
use umath::FF32;
|
use umath::FF32;
|
||||||
|
|
||||||
/// Trait for blending pixels together.
|
/// Trait for blending pixels together.
|
||||||
|
@ -26,9 +27,8 @@ impl Blend<4> for [u8; 4] {
|
||||||
self[..3].copy_from_slice(
|
self[..3].copy_from_slice(
|
||||||
&fg.trunc()
|
&fg.trunc()
|
||||||
// SAFETY: no u8 can possibly become INF / NAN
|
// SAFETY: no u8 can possibly become INF / NAN
|
||||||
.pmap(bg.trunc(), |f, b| unsafe {
|
.zip(bg.trunc())
|
||||||
(f * fg[3] + b * bg[3] * (FF32::new(1.0) - fg[3])) / a
|
.map(|(f, b)| unsafe { (f * fg[3] + b * bg[3] * (FF32::new(1.0) - fg[3])) / a })
|
||||||
})
|
|
||||||
.unfloat(),
|
.unfloat(),
|
||||||
);
|
);
|
||||||
self[3] = unfloat(a);
|
self[3] = unfloat(a);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! provides From's for pixels.
|
//! provides From's for pixels.
|
||||||
|
use atools::prelude::*;
|
||||||
use super::{Push, Trunc};
|
|
||||||
|
|
||||||
/// Converts a pixel to another pixel.
|
/// Converts a pixel to another pixel.
|
||||||
pub trait PFrom<const N: usize> {
|
pub trait PFrom<const N: usize> {
|
||||||
|
@ -38,19 +37,19 @@ impl PFrom<4> for Y {
|
||||||
pub type YA = [u8; 2];
|
pub type YA = [u8; 2];
|
||||||
impl PFrom<1> for YA {
|
impl PFrom<1> for YA {
|
||||||
fn pfrom(f: Y) -> Self {
|
fn pfrom(f: Y) -> Self {
|
||||||
f.and(255)
|
f.join(255)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PFrom<3> for YA {
|
impl PFrom<3> for YA {
|
||||||
fn pfrom(f: RGB) -> Self {
|
fn pfrom(f: RGB) -> Self {
|
||||||
Y::pfrom(f).and(255)
|
Y::pfrom(f).join(255)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PFrom<4> for YA {
|
impl PFrom<4> for YA {
|
||||||
fn pfrom(f: RGBA) -> Self {
|
fn pfrom(f: RGBA) -> Self {
|
||||||
Y::pfrom(f.trunc()).and(255)
|
Y::pfrom(f.trunc()).join(255)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,18 +79,18 @@ pub type RGBA = [u8; 4];
|
||||||
|
|
||||||
impl PFrom<1> for RGBA {
|
impl PFrom<1> for RGBA {
|
||||||
fn pfrom([y]: Y) -> Self {
|
fn pfrom([y]: Y) -> Self {
|
||||||
[y; 3].and(255)
|
[y; 3].join(255)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PFrom<2> for RGBA {
|
impl PFrom<2> for RGBA {
|
||||||
fn pfrom([y, a]: YA) -> Self {
|
fn pfrom([y, a]: YA) -> Self {
|
||||||
[y; 3].and(a)
|
[y; 3].join(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PFrom<3> for RGBA {
|
impl PFrom<3> for RGBA {
|
||||||
fn pfrom(f: [u8; 3]) -> Self {
|
fn pfrom(f: [u8; 3]) -> Self {
|
||||||
f.and(255)
|
f.join(255)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ pub mod blending;
|
||||||
mod utility;
|
mod utility;
|
||||||
mod wam;
|
mod wam;
|
||||||
pub use blending::Blend;
|
pub use blending::Blend;
|
||||||
pub(crate) use utility::{float, unfloat, Floatify, PMap, Push, Trunc, Unfloatify};
|
pub(crate) use utility::{float, unfloat, Floatify, Unfloatify};
|
||||||
pub(crate) use wam::Wam;
|
pub(crate) use wam::Wam;
|
||||||
pub mod convert;
|
pub mod convert;
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub trait Floatify<const N: usize> {
|
||||||
|
|
||||||
/// computes n / 255
|
/// computes n / 255
|
||||||
pub fn float(n: u8) -> FF32 {
|
pub fn float(n: u8) -> FF32 {
|
||||||
// SAFETY: 0..=255 / 0..=255 maynt ever be NAN / INF
|
// SAFETY: 0..=255 / 0..=255 mayn't ever be NAN / INF
|
||||||
unsafe { FF32::new(n as f32) / FF32::new(255.0) }
|
unsafe { FF32::new(n as f32) / FF32::new(255.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,51 +39,3 @@ impl<const N: usize> Floatify<N> for [u8; N] {
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
impl<const N:usize>Floatify<N>for[FF32;N]{fn float(self)->[FF32;N]{self}}
|
impl<const N:usize>Floatify<N>for[FF32;N]{fn float(self)->[FF32;N]{self}}
|
||||||
|
|
||||||
pub trait PMap<T, R, const N: usize> {
|
|
||||||
/// think of it like a `a.zip(b).map(f).collect::<[]>()`
|
|
||||||
fn pmap(self, with: Self, f: impl FnMut(T, T) -> R) -> [R; N];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T: Copy, R: Copy> PMap<T, R, N> for [T; N] {
|
|
||||||
fn pmap(self, with: Self, mut f: impl FnMut(T, T) -> R) -> [R; N] {
|
|
||||||
let mut iter = self.into_iter().zip(with).map(|(a, b)| f(a, b));
|
|
||||||
std::array::from_fn(|_| iter.next().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Trunc<T, const N: usize> {
|
|
||||||
/// it does `a[..a.len() - 1].try_into().unwrap()`.
|
|
||||||
fn trunc(&self) -> [T; N - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T: Copy> Trunc<T, N> for [T; N] {
|
|
||||||
fn trunc(&self) -> [T; N - 1] {
|
|
||||||
self[..N - 1].try_into().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Push<T, const N: usize> {
|
|
||||||
fn and(self, and: T) -> [T; N + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> Push<T, N> for [T; N] {
|
|
||||||
fn and(self, and: T) -> [T; N + 1] {
|
|
||||||
let mut iter = self.into_iter().chain(std::iter::once(and));
|
|
||||||
std::array::from_fn(|_| iter.next().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn trunc() {
|
|
||||||
let x = [1];
|
|
||||||
assert_eq!(x.trunc(), []);
|
|
||||||
let x = [1, 2, 3, 4];
|
|
||||||
assert_eq!(x.trunc(), [1, 2, 3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append() {
|
|
||||||
let x = [1];
|
|
||||||
assert_eq!(x.and(5), [1, 5]);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
use super::{float, unfloat};
|
||||||
|
use atools::prelude::*;
|
||||||
use umath::{generic_float::Constructors, FF32};
|
use umath::{generic_float::Constructors, FF32};
|
||||||
|
|
||||||
use super::{float, unfloat, PMap};
|
|
||||||
|
|
||||||
pub trait Wam {
|
pub trait Wam {
|
||||||
/// this function weighs the sides and combines
|
/// this function weighs the sides and combines
|
||||||
///
|
///
|
||||||
|
@ -14,7 +14,7 @@ pub trait Wam {
|
||||||
impl<const N: usize> Wam for [u8; N] {
|
impl<const N: usize> Wam for [u8; N] {
|
||||||
unsafe fn wam(self, b: Self, l: FF32, r: FF32) -> Self {
|
unsafe fn wam(self, b: Self, l: FF32, r: FF32) -> Self {
|
||||||
// SAFETY: read [`weigh`]
|
// SAFETY: read [`weigh`]
|
||||||
self.pmap(b, |a, b| unsafe { weigh(a, b, l, r) })
|
self.zip(b).map(|(a, b)| unsafe { weigh(a, b, l, r) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ impl<const N: usize> Wam for [u8; N] {
|
||||||
///
|
///
|
||||||
/// floats must be smart
|
/// floats must be smart
|
||||||
unsafe fn weigh(a: u8, b: u8, l: FF32, r: FF32) -> u8 {
|
unsafe fn weigh(a: u8, b: u8, l: FF32, r: FF32) -> u8 {
|
||||||
// SAFETY: float(x) returns 0..=1, 0..=1 * f32::MAX isnt Inf, but if you add 1.0 and then mul by max again, you get inf (big bad, hence unsafe fn)
|
// SAFETY: float(x) returns 0..=1, 0..=1 * f32::MAX isn't Inf, but if you add 1.0 and then mul by max again, you get inf (big bad, hence unsafe fn)
|
||||||
unsafe { unfloat((float(a) * l + float(b) * r).clamp(FF32::zero(), FF32::one())) }
|
unsafe { unfloat((float(a) * l + float(b) * r).clamp(FF32::zero(), FF32::one())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl<T: AsRef<[u8]>> Image<T, 4> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image<Box<[u8]>, 4> {
|
impl Image<Box<[u8]>, 4> {
|
||||||
/// Downlodas a purportedly [`TextureFormat::Rgba8Unorm`] image from the gpu.
|
/// Downloads a purportedly [`TextureFormat::Rgba8Unorm`] image from the gpu.
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// When a "error occurs while trying to async map a buffer".
|
/// When a "error occurs while trying to async map a buffer".
|
||||||
|
|
Loading…
Reference in a new issue