fast image operations
packing trait
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/blur.rs | 8 | ||||
| -rw-r--r-- | src/convert.rs | 36 | ||||
| -rw-r--r-- | src/drawing/text.rs | 8 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/pack.rs | 55 | ||||
| -rw-r--r-- | src/show.rs | 4 |
7 files changed, 73 insertions, 42 deletions
@@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.25" +version = "0.4.26" authors = ["bend-n <[email protected]>"] license = "MIT" edition = "2021" diff --git a/src/blur.rs b/src/blur.rs index 62ec9fa..7f00b8f 100644 --- a/src/blur.rs +++ b/src/blur.rs @@ -1,6 +1,6 @@ use stackblur_iter::imgref::ImgRefMut; -use crate::{pixels::convert::PFrom, Image}; +use crate::Image; impl<T: AsMut<[u32]> + AsRef<[u32]>> Image<T, 1> { /// Blur a image of packed 32 bit integers, `[0xAARRGGBB]`. @@ -13,8 +13,7 @@ impl<T: AsMut<[u32]> + AsRef<[u32]>> Image<T, 1> { impl<const N: usize> Image<Box<[u8]>, N> where - [u8; 4]: PFrom<N>, - [u8; N]: PFrom<4>, + [u8; N]: crate::Pack, { /// Blur a image. /// ``` @@ -38,8 +37,7 @@ where impl<const N: usize> Image<&[u8], N> where - [u8; 4]: PFrom<N>, - [u8; N]: PFrom<4>, + [u8; N]: crate::Pack, { /// Blur a image. pub fn blur(self, radius: usize) -> Image<Box<[u8]>, N> { diff --git a/src/convert.rs b/src/convert.rs index 3c6c54f..2b0d192 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,6 +1,6 @@ //! define From's for images. //! these conversions are defined by [`PFrom`]. -use crate::{pixels::convert::PFrom, Image}; +use crate::{pixels::convert::PFrom, Image, Pack}; fn map<const A: usize, const B: usize>(image: Image<&[u8], A>) -> Image<Box<[u8]>, B> where @@ -64,33 +64,13 @@ boxconv!(4 => 1); boxconv!(4 => 2); boxconv!(4 => 3); -#[inline] -pub const fn pack([r, g, b, a]: [u8; 4]) -> u32 { - ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) -} - -#[inline] -pub const fn unpack(n: u32) -> [u8; 4] { - [ - ((n >> 16) & 0xFF) as u8, - ((n >> 8) & 0xFF) as u8, - (n & 0xFF) as u8, - ((n >> 24) & 0xFF) as u8, - ] -} - impl<const N: usize> From<Image<&[u8], N>> for Image<Box<[u32]>, 1> where - [u8; 4]: PFrom<N>, + [u8; N]: Pack, { /// Pack into ARGB. fn from(value: Image<&[u8], N>) -> Self { - let buf = value - .chunked() - .copied() - .map(PFrom::pfrom) - .map(pack) - .collect(); + let buf = value.chunked().map(Pack::pack).collect(); // SAFETY: ctor unsafe { Self::new(value.width, value.height, buf) } } @@ -98,18 +78,14 @@ where pub fn unpack_all<const N: usize>(buffer: &[u32]) -> impl Iterator<Item = u8> + '_ where - [u8; N]: PFrom<4>, + [u8; N]: Pack, { - buffer - .iter() - .copied() - .map(unpack) - .flat_map(<[u8; N] as PFrom<4>>::pfrom) + buffer.iter().copied().flat_map(<[u8; N]>::unpack) } impl<const N: usize> From<Image<&[u32], 1>> for Image<Box<[u8]>, N> where - [u8; N]: PFrom<4>, + [u8; N]: Pack, { fn from(value: Image<&[u32], 1>) -> Self { let buf = unpack_all(value.buffer).collect(); diff --git a/src/drawing/text.rs b/src/drawing/text.rs index 192230a..b0b8da2 100644 --- a/src/drawing/text.rs +++ b/src/drawing/text.rs @@ -1,9 +1,8 @@ //! text raster use crate::{ - convert::{pack, unpack}, pixels::{float, Wam}, - Image, + Image, Pack, }; use fontdue::{layout::TextStyle, Font}; use umath::{generic_float::Constructors, FF32}; @@ -37,11 +36,12 @@ impl Image<&mut [u32], 1> { // SAFETY: the rasterizer kinda promises that metrics width and height are in bounds let fill = unsafe { float(*bitmap.get_unchecked(j * metrics.width + i)) }; // SAFETY: we clampin - let bg = unsafe { unpack(*self.buffer.get_unchecked(self.at(x, y))) }; + let bg: [u8; 4] = + unsafe { Pack::unpack(*self.buffer.get_unchecked(self.at(x, y))) }; // SAFETY: see above *unsafe { self.buffer.get_unchecked_mut(self.at(x, y)) } = // SAFETY: fill is 0..=1 - pack(unsafe { bg.wam(color, FF32::one() - fill, fill) }); + Pack::pack(unsafe { &bg.wam(color, FF32::one() - fill, fill) }); } } } @@ -84,6 +84,8 @@ mod drawing; mod r#dyn; pub(crate) mod math; mod overlay; +mod pack; +pub use pack::Pack; pub mod pixels; #[cfg(feature = "scale")] pub mod scale; diff --git a/src/pack.rs b/src/pack.rs new file mode 100644 index 0000000..82d41bb --- /dev/null +++ b/src/pack.rs @@ -0,0 +1,55 @@ +//! trait for packing pixels + +use crate::pixels::convert::{PFrom, RGB, RGBA, Y, YA}; + +#[inline] +pub const fn pack([r, g, b, a]: [u8; 4]) -> u32 { + ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32) +} + +#[inline] +pub const fn unpack(n: u32) -> [u8; 4] { + [ + ((n >> 16) & 0xFF) as u8, + ((n >> 8) & 0xFF) as u8, + (n & 0xFF) as u8, + ((n >> 24) & 0xFF) as u8, + ] +} + +/// packs and unpacks this pixel +/// note that `unpack(pack(p))` may not equal `p` +pub trait Pack<P = u32> { + /// pack this pixel + fn pack(&self) -> P; + /// unpacks this pixel + fn unpack(from: P) -> Self; +} + +macro_rules! simple { + ($p:ident) => { + impl Pack for $p { + fn pack(&self) -> u32 { + pack(PFrom::pfrom(*self)) + } + + fn unpack(from: u32) -> $p { + PFrom::pfrom(unpack(from)) + } + } + }; +} +simple!(RGBA); +simple!(RGB); +simple!(YA); +simple!(Y); + +impl Pack<u8> for Y { + fn pack(&self) -> u8 { + self[0] + } + + fn unpack(from: u8) -> Self { + [from] + } +} diff --git a/src/show.rs b/src/show.rs index 25040cb..f38dbc3 100644 --- a/src/show.rs +++ b/src/show.rs @@ -2,12 +2,12 @@ use crate::Image; #[cfg(feature = "real-show")] mod real { - use crate::{pixels::convert::PFrom, Image}; + use crate::Image; use minifb::{Key, Window}; pub fn show<const CHANNELS: usize>(i: Image<&[u8], CHANNELS>) where - [u8; 4]: PFrom<CHANNELS>, + [u8; CHANNELS]: crate::Pack, { let mut win = Window::new( "show", |