packing trait

This commit is contained in:
bendn 2023-11-14 15:01:32 +07:00
parent 3b69335dcd
commit 669a541bb7
No known key found for this signature in database
GPG key ID: 0D9D3A2A3B2A93D6
7 changed files with 73 additions and 42 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "fimg" name = "fimg"
version = "0.4.25" version = "0.4.26"
authors = ["bend-n <bend.n@outlook.com>"] authors = ["bend-n <bend.n@outlook.com>"]
license = "MIT" license = "MIT"
edition = "2021" edition = "2021"

View file

@ -1,6 +1,6 @@
use stackblur_iter::imgref::ImgRefMut; use stackblur_iter::imgref::ImgRefMut;
use crate::{pixels::convert::PFrom, Image}; use crate::Image;
impl<T: AsMut<[u32]> + AsRef<[u32]>> Image<T, 1> { impl<T: AsMut<[u32]> + AsRef<[u32]>> Image<T, 1> {
/// Blur a image of packed 32 bit integers, `[0xAARRGGBB]`. /// 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> impl<const N: usize> Image<Box<[u8]>, N>
where where
[u8; 4]: PFrom<N>, [u8; N]: crate::Pack,
[u8; N]: PFrom<4>,
{ {
/// Blur a image. /// Blur a image.
/// ``` /// ```
@ -38,8 +37,7 @@ where
impl<const N: usize> Image<&[u8], N> impl<const N: usize> Image<&[u8], N>
where where
[u8; 4]: PFrom<N>, [u8; N]: crate::Pack,
[u8; N]: PFrom<4>,
{ {
/// Blur a image. /// Blur a image.
pub fn blur(self, radius: usize) -> Image<Box<[u8]>, N> { pub fn blur(self, radius: usize) -> Image<Box<[u8]>, N> {

View file

@ -1,6 +1,6 @@
//! define From's for images. //! define From's for images.
//! these conversions are defined by [`PFrom`]. //! 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> fn map<const A: usize, const B: usize>(image: Image<&[u8], A>) -> Image<Box<[u8]>, B>
where where
@ -64,33 +64,13 @@ boxconv!(4 => 1);
boxconv!(4 => 2); boxconv!(4 => 2);
boxconv!(4 => 3); 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> impl<const N: usize> From<Image<&[u8], N>> for Image<Box<[u32]>, 1>
where where
[u8; 4]: PFrom<N>, [u8; N]: Pack,
{ {
/// Pack into ARGB. /// Pack into ARGB.
fn from(value: Image<&[u8], N>) -> Self { fn from(value: Image<&[u8], N>) -> Self {
let buf = value let buf = value.chunked().map(Pack::pack).collect();
.chunked()
.copied()
.map(PFrom::pfrom)
.map(pack)
.collect();
// SAFETY: ctor // SAFETY: ctor
unsafe { Self::new(value.width, value.height, buf) } 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> + '_ pub fn unpack_all<const N: usize>(buffer: &[u32]) -> impl Iterator<Item = u8> + '_
where where
[u8; N]: PFrom<4>, [u8; N]: Pack,
{ {
buffer buffer.iter().copied().flat_map(<[u8; N]>::unpack)
.iter()
.copied()
.map(unpack)
.flat_map(<[u8; N] as PFrom<4>>::pfrom)
} }
impl<const N: usize> From<Image<&[u32], 1>> for Image<Box<[u8]>, N> impl<const N: usize> From<Image<&[u32], 1>> for Image<Box<[u8]>, N>
where where
[u8; N]: PFrom<4>, [u8; N]: Pack,
{ {
fn from(value: Image<&[u32], 1>) -> Self { fn from(value: Image<&[u32], 1>) -> Self {
let buf = unpack_all(value.buffer).collect(); let buf = unpack_all(value.buffer).collect();

View file

@ -1,9 +1,8 @@
//! text raster //! text raster
use crate::{ use crate::{
convert::{pack, unpack},
pixels::{float, Wam}, pixels::{float, Wam},
Image, Image, Pack,
}; };
use fontdue::{layout::TextStyle, Font}; use fontdue::{layout::TextStyle, Font};
use umath::{generic_float::Constructors, FF32}; 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 // SAFETY: the rasterizer kinda promises that metrics width and height are in bounds
let fill = unsafe { float(*bitmap.get_unchecked(j * metrics.width + i)) }; let fill = unsafe { float(*bitmap.get_unchecked(j * metrics.width + i)) };
// SAFETY: we clampin // 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 // SAFETY: see above
*unsafe { self.buffer.get_unchecked_mut(self.at(x, y)) } = *unsafe { self.buffer.get_unchecked_mut(self.at(x, y)) } =
// SAFETY: fill is 0..=1 // SAFETY: fill is 0..=1
pack(unsafe { bg.wam(color, FF32::one() - fill, fill) }); Pack::pack(unsafe { &bg.wam(color, FF32::one() - fill, fill) });
} }
} }
} }

View file

@ -84,6 +84,8 @@ mod drawing;
mod r#dyn; mod r#dyn;
pub(crate) mod math; pub(crate) mod math;
mod overlay; mod overlay;
mod pack;
pub use pack::Pack;
pub mod pixels; pub mod pixels;
#[cfg(feature = "scale")] #[cfg(feature = "scale")]
pub mod scale; pub mod scale;

55
src/pack.rs Normal file
View file

@ -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]
}
}

View file

@ -2,12 +2,12 @@ use crate::Image;
#[cfg(feature = "real-show")] #[cfg(feature = "real-show")]
mod real { mod real {
use crate::{pixels::convert::PFrom, Image}; use crate::Image;
use minifb::{Key, Window}; use minifb::{Key, Window};
pub fn show<const CHANNELS: usize>(i: Image<&[u8], CHANNELS>) pub fn show<const CHANNELS: usize>(i: Image<&[u8], CHANNELS>)
where where
[u8; 4]: PFrom<CHANNELS>, [u8; CHANNELS]: crate::Pack,
{ {
let mut win = Window::new( let mut win = Window::new(
"show", "show",