fast image operations
Diffstat (limited to 'src/sub.rs')
-rw-r--r--src/sub.rs181
1 files changed, 0 insertions, 181 deletions
diff --git a/src/sub.rs b/src/sub.rs
deleted file mode 100644
index 531bfe7..0000000
--- a/src/sub.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-use std::{marker::PhantomData, num::NonZeroU32};
-
-use crate::Image;
-
-/// A smaller part of a larger image.
-///
-/// ```text
-/// ┏━━━━━━━━━━━━━━┓ hard borders represent the full image
-/// ┃ 1 2 3 1 ┃ vvvv the top left of the new image
-/// ┃ ┌──────┐ ┃ crop(2, 2).from(1, 1)
-/// ┃ 4 │ 5 6 │ 2 ┃ ^^^^ width and height
-/// ┃ │ │ ┃
-/// ┃ 7 │ 8 9 │ 3 ┃
-/// ┗━━━┷━━━━━━┷━━━┛ soft borders represent the new image
-/// ```
-#[derive(Clone)]
-pub struct SubImage<T, const CHANNELS: usize> {
- inner: Image<T, CHANNELS>,
- /// in pixels
- offset_x: u32,
- real_width: NonZeroU32,
- real_height: NonZeroU32,
-}
-
-/// Trait for cropping a image.
-pub trait Cropper<T, const C: usize> {
- /// # Panics
- ///
- /// if w - y == 0
- fn from(self, x: u32, y: u32) -> SubImage<T, C>;
-}
-
-impl<T: Clone, const N: usize> Copy for SubImage<T, N> where Image<T, N>: Copy {}
-
-macro_rules! def {
- ($t:ty, $($what:ident)?) => {
- struct Crop<'a, T, const C: usize> {
- dimensions: (NonZeroU32, NonZeroU32),
- _d: PhantomData<SubImage<$t, C>>,
- image: Image<$t, C>,
- }
-
- impl<'a, T, const C: usize> Cropper<$t, C> for Crop<'a, T, C> {
- fn from(self, x: u32, y: u32) -> SubImage<$t, C> {
- let w = self.image.width();
- // SAFETY: ctor
- let i = unsafe {
- Image::new(
- self.image.width,
- NonZeroU32::new(self.image.height() - y).unwrap(),
- &$($what)?(self.image.take_buffer()[(y as usize * C) * w as usize..]),
- )
- };
- SubImage {
- offset_x: x,
- inner: i,
- real_width: self.dimensions.0,
- real_height: self.dimensions.1,
- }
- }
- }
- };
-}
-
-impl<T, const C: usize> Image<T, C> {
- /// Crop a image.
- ///
- /// The signature looks something like: `i.crop(width, height).from(top_left_x, top_left_y)`, which gives you a <code>[SubImage]<&\[T\], _></code>
- ///
- /// If you want a owned image, `i.crop(w, h).from(x, y).own()` gets you a <code>[`Image`]<[Box]<\[T\], _>></code> back.
- ///
- /// ```
- /// # use fimg::{Image, Cropper};
- /// let mut i = Image::<_, 1>::build(4, 3).buf([
- /// 1, 2, 3, 1,
- /// 4, 5, 6, 2,
- /// 7, 8, 9, 3,
- /// ]);
- /// let c = i.crop(2, 2).from(1, 1);
- /// # unsafe {
- /// assert_eq!(c.pixel(0, 0), [5]);
- /// assert_eq!(c.pixel(1, 1), [9]);
- /// assert_eq!(
- /// c.own().bytes(),
- /// &[5, 6,
- /// 8, 9]
- /// );
- /// # }
- /// ```
- ///
- /// # Panics
- ///
- /// if width == 0 || height == 0
- pub fn crop<'a, U: 'a>(&'a self, width: u32, height: u32) -> impl Cropper<&'a [U], C>
- where
- T: AsRef<[U]>,
- {
- def!(&'a [T],);
- Crop {
- dimensions: (
- NonZeroU32::new(width).expect("Image::crop panics when width == 0"),
- NonZeroU32::new(height).expect("Image::crop panics when height == 0"),
- ),
- _d: PhantomData,
- image: self.as_ref(),
- }
- }
-
- /// Like [`Image::crop`], but returns a mutable [`SubImage`].
- pub fn crop_mut<'a, U: 'a>(
- &'a mut self,
- width: u32,
- height: u32,
- ) -> impl Cropper<&'a mut [U], C>
- where
- T: AsMut<[U]> + AsRef<[U]>,
- {
- def!(&'a mut [T], mut);
- Crop {
- dimensions: (
- NonZeroU32::new(width).expect("Image::crop panics when width == 0"),
- NonZeroU32::new(height).expect("Image::crop panics when height == 0"),
- ),
- _d: PhantomData,
- image: self.as_mut(),
- }
- }
-}
-
-impl<T: Clone, const C: usize> SubImage<&[T], C> {
- /// Clones this [`SubImage`] into its own [`Image`]
- pub fn own(&self) -> Image<Box<[T]>, C> {
- let mut out = Vec::with_capacity(
- self.real_width.get() as usize * self.real_height.get() as usize * C,
- );
-
- for row in self.inner.rows().take(self.real_height.get() as usize) {
- out.extend_from_slice(
- &row[self.offset_x as usize
- ..self.offset_x as usize + self.real_width.get() as usize]
- .as_flattened(),
- );
- }
- // SAFETY: ctor
- unsafe { Image::new(self.real_width, self.real_height, out.into()) }
- }
-}
-
-// TODO crop()
-impl<W, const C: usize> SubImage<W, C> {
- /// Get a pixel.
- ///
- /// # Safety
- ///
- /// this pixel must be in bounds.
- pub unsafe fn pixel<U: Copy>(&self, x: u32, y: u32) -> &[U; C]
- where
- W: AsRef<[U]>,
- {
- // note: if you get a pixel, in release mode, that is in bounds of the outer image, but not the sub image, that would be library-ub.
- debug_assert!(x < self.real_width.get());
- debug_assert!(y < self.real_height.get());
- // SAFETY: caller
- unsafe { self.inner.pixel(x + self.offset_x, y) }
- }
-
- /// Get a pixel, mutably.
- ///
- /// # Safety
- ///
- /// this pixel must be in bounds.
- pub unsafe fn pixel_mut<U: Copy>(&mut self, x: u32, y: u32) -> &mut [U]
- where
- W: AsMut<[U]> + AsRef<[U]>,
- {
- debug_assert!(x < self.real_width.get());
- debug_assert!(y < self.real_height.get());
- // SAFETY: caller
- unsafe { self.inner.pixel_mut(x, y) }
- }
-}