diff --git a/Cargo.toml b/Cargo.toml index 52a69ab..6594107 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.25" +version = "0.4.26" authors = ["bend-n "] 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 + AsRef<[u32]>> Image { /// Blur a image of packed 32 bit integers, `[0xAARRGGBB]`. @@ -13,8 +13,7 @@ impl + AsRef<[u32]>> Image { impl Image, N> where - [u8; 4]: PFrom, - [u8; N]: PFrom<4>, + [u8; N]: crate::Pack, { /// Blur a image. /// ``` @@ -38,8 +37,7 @@ where impl Image<&[u8], N> where - [u8; 4]: PFrom, - [u8; N]: PFrom<4>, + [u8; N]: crate::Pack, { /// Blur a image. pub fn blur(self, radius: usize) -> Image, 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(image: Image<&[u8], A>) -> Image, 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 From> for Image, 1> where - [u8; 4]: PFrom, + [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(buffer: &[u32]) -> impl Iterator + '_ 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 From> for Image, 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) }); } } } diff --git a/src/lib.rs b/src/lib.rs index f4317a2..46dc7d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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

{ + /// 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 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(i: Image<&[u8], CHANNELS>) where - [u8; 4]: PFrom, + [u8; CHANNELS]: crate::Pack, { let mut win = Window::new( "show",