fast image operations
add array_chunks
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/convert.rs | 5 | ||||
| -rw-r--r-- | src/drawing/text.rs | 10 | ||||
| -rw-r--r-- | src/lib.rs | 8 | ||||
| -rw-r--r-- | src/overlay.rs | 3 | ||||
| -rw-r--r-- | src/show.rs | 6 |
6 files changed, 14 insertions, 19 deletions
@@ -29,6 +29,7 @@ qwant = { version = "1.0.0", optional = true } libc = "0.2.154" hinted = { version = "0.0.2", features = ["nightly"] } lower = "0.2.0" +array_chunks = "1.0.0" [target.'cfg(windows)'.dependencies] windows = { version = "0.53.0", features = [ diff --git a/src/convert.rs b/src/convert.rs index 4086ebc..daa04fb 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,10 +1,11 @@ //! define From's for images. //! these conversions are defined by [`PFrom`]. -use crate::{pixels::convert::PFrom, Image, Pack}; +use crate::{Image, Pack, pixels::convert::PFrom}; +use array_chunks::*; use core::intrinsics::{fmul_algebraic, fsub_algebraic, transmute_unchecked as transmute}; use std::{ mem::MaybeUninit as MU, - simd::{prelude::*, SimdElement, StdFloat}, + simd::{SimdElement, StdFloat, prelude::*}, }; fn map<const A: usize, const B: usize>(image: Image<&[u8], A>) -> Image<Box<[u8]>, B> diff --git a/src/drawing/text.rs b/src/drawing/text.rs index 7c03101..00a2d65 100644 --- a/src/drawing/text.rs +++ b/src/drawing/text.rs @@ -1,11 +1,11 @@ //! text raster use crate::{ - pixels::{float, Wam}, Image, Pack, + pixels::{Wam, float}, }; -use fontdue::{layout::TextStyle, Font}; -use umath::{generic_float::Constructors, FF32}; +use fontdue::{Font, layout::TextStyle}; +use umath::{FF32, generic_float::Constructors}; /// note: `N` may != channels pub trait Text<const N: usize> { @@ -37,7 +37,7 @@ impl<T: AsMut<[u32]> + AsRef<[u32]>> Text<4> for Image<T, 1> { // SAFETY: see above *(&mut unsafe { self.pixel_mut(x, y) }[0]) = // SAFETY: fill is 0..=1 - Pack::pack(unsafe { &bg.wam(color, FF32::one() - fill, fill) }); + Pack::pack(& bg.wam(color, 1.0 - fill, fill)); } } } @@ -67,7 +67,7 @@ impl<const N: usize, T: AsMut<[u8]> + AsRef<[u8]>> Text<N> for Image<T, N> { // SAFETY: we clampin let bg = unsafe { &mut *(self.pixel_mut(x, y).as_mut_ptr() as *mut [u8; N]) }; // SAFETY: fill is 0..=1 - *bg = unsafe { bg.wam(color, FF32::one() - fill, fill) }; + *bg = unsafe { bg.wam(color, *(FF32::one() - fill), fill) }; } } } @@ -63,9 +63,7 @@ portable_simd, array_windows, doc_auto_cfg, - array_chunks, iter_chain, - let_chains, try_blocks, test )] @@ -86,6 +84,7 @@ confusable_idents, internal_features )] +use array_chunks::*; use hinted::HintExt; use std::{hint::assert_unchecked, intrinsics::transmute_unchecked, num::NonZeroU32, ops::Range}; @@ -149,11 +148,8 @@ trait At { } impl At for (u32, u32) { - #[cfg_attr(debug_assertions, track_caller)] #[inline] fn at<const C: usize>(self, x: u32, y: u32) -> usize { - debug_assert!(x < self.0, "x out of bounds"); - debug_assert!(y < self.1, "y out of bounds"); #[allow(clippy::multiple_unsafe_ops_per_block)] // SAFETY: me when uncheck math: 😧 (FIXME) let index = unsafe { @@ -476,13 +472,11 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> { /// /// the output index is not guaranteed to be in bounds #[inline] - #[cfg_attr(debug_assertions, track_caller)] fn slice<U>(&self, x: u32, y: u32) -> Range<usize> where T: AsRef<[U]>, { let index = self.at(x, y); - debug_assert!(self.len() > index); // SAFETY: as long as the buffer isnt wrong, this is 😄 index..unsafe { index.unchecked_add(CHANNELS) } } diff --git a/src/overlay.rs b/src/overlay.rs index 2ab451b..08f3caf 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -188,7 +188,6 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>> Image<T, 3> { impl ClonerOverlay<4, 4> for ImageCloner<'_, 4> { #[inline] - #[must_use = "function does not modify the original image"] unsafe fn overlay(&self, with: &Image<&[u8], 4>) -> Image<Vec<u8>, 4> { let mut out = self.dup(); // SAFETY: same @@ -363,7 +362,6 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Imag impl ClonerOverlay<4, 3> for ImageCloner<'_, 3> { #[inline] - #[must_use = "function does not modify the original image"] unsafe fn overlay(&self, with: &Image<&[u8], 4>) -> Image<Vec<u8>, 3> { let mut out = self.dup(); // SAFETY: same @@ -393,7 +391,6 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for Im impl ClonerOverlayAt<4, 4> for ImageCloner<'_, 4> { #[inline] - #[must_use = "function does not modify the original image"] unsafe fn overlay_at(&self, with: &Image<&[u8], 4>, x: u32, y: u32) -> Image<Vec<u8>, 4> { let mut out = self.dup(); // SAFETY: same diff --git a/src/show.rs b/src/show.rs index 2a220f4..21b73a3 100644 --- a/src/show.rs +++ b/src/show.rs @@ -3,7 +3,7 @@ use crate::Image; #[cfg(feature = "real-show")] mod real { use crate::Image; - use minifb::{Key, Window}; + use minifb::{Key, Window, WindowOptions}; pub fn show<const CHANNELS: usize>(i: Image<&[u8], CHANNELS>) where @@ -16,6 +16,7 @@ mod real { Default::default(), ) .unwrap(); + win.set_title("image viewer"); let font = fontdue::Font::from_bytes( &include_bytes!("../data/CascadiaCode.ttf")[..], fontdue::FontSettings { @@ -34,6 +35,7 @@ mod real { .map(|(x, y)| (x.min(i.width()), y.min(i.height()))) { // SAFETY: ctor + let pix = unsafe { i.pixel(x, y) }; unsafe { Image::new(buf.width, buf.height, &mut *buf.buffer) }.text( 5, i.height() - 20, @@ -42,7 +44,7 @@ mod real { &format!( "P ({x}, {y}), {}", // SAFETY: clampd - match unsafe { &i.pixel(x, y)[..] } { + match &pix[..] { [y] => format!("(Y {y})"), [y, a] => format!("(Y {y} A {a})"), [r, g, b] => format!("(R {r} G {g} B {b})"), |