fast image operations
-rw-r--r--Cargo.toml2
-rw-r--r--benches/affine_transformations.rs5
-rw-r--r--benches/drawing.rs6
-rw-r--r--benches/overlays.rs6
-rw-r--r--src/affine.rs16
-rw-r--r--src/drawing/box.rs4
-rw-r--r--src/drawing/circle.rs4
-rw-r--r--src/drawing/line.rs4
-rw-r--r--src/drawing/poly.rs3
-rw-r--r--src/drawing/tri.rs4
-rw-r--r--src/lib.rs81
-rw-r--r--src/overlay.rs29
12 files changed, 101 insertions, 63 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 8a2d866..21a9af8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "fimg"
-version = "0.4.13"
+version = "0.4.14"
authors = ["bend-n <[email protected]>"]
license = "MIT"
edition = "2021"
diff --git a/benches/affine_transformations.rs b/benches/affine_transformations.rs
index 912eff0..8ac03a4 100644
--- a/benches/affine_transformations.rs
+++ b/benches/affine_transformations.rs
@@ -3,12 +3,13 @@ use fimg::*;
macro_rules! bench {
(fn $name: ident() { run $fn: ident() } $($namec:ident)?) => {
fn $name() {
+ let mut bytes = *include_bytes!("4_128x128.imgbuf");
let mut img: Image<_, 4> =
- Image::build(128, 128).buf(include_bytes!("4_128x128.imgbuf").to_vec());
+ Image::build(128, 128).buf(&mut bytes);
for _ in 0..256 {
#[allow(unused_unsafe)]
unsafe {
- img.$fn()
+ img.as_mut().$fn()
};
}
}
diff --git a/benches/drawing.rs b/benches/drawing.rs
index 1ad9c97..b0668d3 100644
--- a/benches/drawing.rs
+++ b/benches/drawing.rs
@@ -1,7 +1,7 @@
use fimg::*;
fn tri() {
- let mut b = [0u8; 1000 * 1000 * 4];
- let mut i = Image::<&mut [u8], 4>::build(1000, 1000).buf(&mut b);
- i.tri((0., 0.), (1000., 500.), (0., 999.), [255, 255, 255, 255]);
+ let mut i: Image<_, 4> = fimg::make!(4 channels 1000 x 1000);
+ i.as_mut()
+ .tri((0., 0.), (1000., 500.), (0., 999.), [255, 255, 255, 255]);
}
iai::main!(tri);
diff --git a/benches/overlays.rs b/benches/overlays.rs
index 46e10f6..715a226 100644
--- a/benches/overlays.rs
+++ b/benches/overlays.rs
@@ -1,7 +1,7 @@
use fimg::*;
fn overlay_3on3at() {
- let mut a: Image<_, 3> = Image::alloc(128, 128);
+ let mut a = fimg::make!(3 channels 128 x 128);
let b: Image<&[u8], 3> = Image::build(8, 8).buf(include_bytes!("3_8x8.imgbuf"));
for x in 0..16 {
for y in 0..16 {
@@ -11,7 +11,7 @@ fn overlay_3on3at() {
}
fn overlay_4on3at() {
- let mut a: Image<_, 3> = Image::alloc(128, 128);
+ let mut a = fimg::make!(3 channels 128 x 128);
let b: Image<&[u8], 4> = Image::build(8, 8).buf(include_bytes!("4_8x8.imgbuf"));
for x in 0..16 {
for y in 0..16 {
@@ -21,7 +21,7 @@ fn overlay_4on3at() {
}
fn overlay_4on4at() {
- let mut a: Image<_, 4> = Image::alloc(128, 128);
+ let mut a = fimg::make!(4 channels 128 x 128);
let b: Image<&[u8], 4> = Image::build(8, 8).buf(include_bytes!("4_8x8.imgbuf"));
for x in 0..16 {
for y in 0..16 {
diff --git a/src/affine.rs b/src/affine.rs
index 2568693..b0152a5 100644
--- a/src/affine.rs
+++ b/src/affine.rs
@@ -1,6 +1,4 @@
//! Manages the affine image transformations.
-use std::ops::DerefMut;
-
use crate::{cloner::ImageCloner, Image};
impl<const CHANNELS: usize> ImageCloner<'_, CHANNELS> {
@@ -45,7 +43,7 @@ impl<const CHANNELS: usize> ImageCloner<'_, CHANNELS> {
}
}
-impl<const CHANNELS: usize, T: DerefMut<Target = [u8]>> Image<T, CHANNELS> {
+impl<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>> Image<T, CHANNELS> {
/// Flip an image vertically.
pub fn flip_v(&mut self) {
for y in 0..self.height() / 2 {
@@ -127,7 +125,7 @@ impl<const CHANNELS: usize> ImageCloner<'_, CHANNELS> {
}
}
-impl<const CHANNELS: usize, T: DerefMut<Target = [u8]>> Image<T, CHANNELS> {
+impl<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>> Image<T, CHANNELS> {
/// Rotate an image 180 degrees clockwise.
pub fn rot_180(&mut self) {
self.flatten_mut().reverse();
@@ -162,7 +160,7 @@ impl<const CHANNELS: usize, T: DerefMut<Target = [u8]>> Image<T, CHANNELS> {
/// # Safety
///
/// UB if supplied image not square
-unsafe fn crev<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(mut img: Image<T, CHANNELS>) {
+unsafe fn crev<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(mut img: Image<T, CHANNELS>) {
debug_assert_eq!(img.width(), img.height());
let size = img.width() as usize;
let b = img.flatten_mut();
@@ -202,7 +200,7 @@ unsafe fn transpose_out<const CHANNELS: usize>(
/// # Safety
///
/// UB if supplied image rectangular
-unsafe fn transpose<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
+unsafe fn transpose<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(
img: &mut Image<T, CHANNELS>,
) {
debug_assert_eq!(img.width(), img.height());
@@ -220,7 +218,7 @@ unsafe fn transpose<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
/// # Safety
///
/// UB if image not square
-unsafe fn transpose_non_power_of_two<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
+unsafe fn transpose_non_power_of_two<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(
img: &mut Image<T, CHANNELS>,
) {
debug_assert_eq!(img.width(), img.height());
@@ -239,7 +237,7 @@ const TILE: usize = 4;
/// # Safety
///
/// be careful
-unsafe fn transpose_tile<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
+unsafe fn transpose_tile<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(
img: &mut Image<T, CHANNELS>,
row: usize,
col: usize,
@@ -275,7 +273,7 @@ unsafe fn transpose_tile<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
/// # Safety
///
/// be careful
-unsafe fn transpose_diag<const CHANNELS: usize, T: DerefMut<Target = [u8]>>(
+unsafe fn transpose_diag<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(
img: &mut Image<T, CHANNELS>,
pos: usize,
size: usize,
diff --git a/src/drawing/box.rs b/src/drawing/box.rs
index d59b01b..b4b1d3e 100644
--- a/src/drawing/box.rs
+++ b/src/drawing/box.rs
@@ -1,9 +1,9 @@
//! `Box<cat>`
-use std::ops::{DerefMut, Range};
+use std::ops::Range;
use crate::Image;
-impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Draw a bordered box
/// ```
/// # use fimg::Image;
diff --git a/src/drawing/circle.rs b/src/drawing/circle.rs
index 793dd92..5f9f105 100644
--- a/src/drawing/circle.rs
+++ b/src/drawing/circle.rs
@@ -1,8 +1,8 @@
//! draw 2d circles
use crate::Image;
-use std::ops::DerefMut;
-impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Draws a circle, using the [Bresenham's circle](https://en.wikipedia.org/wiki/Midpoint_circle_algorithm) algorithm.
/// ```
/// # use fimg::Image;
diff --git a/src/drawing/line.rs b/src/drawing/line.rs
index 369e8fd..3498d95 100644
--- a/src/drawing/line.rs
+++ b/src/drawing/line.rs
@@ -1,7 +1,7 @@
//! adds a `line` function to Image
#![allow(clippy::missing_docs_in_private_items)]
use crate::Image;
-use std::{iter::Iterator, ops::DerefMut};
+use std::iter::Iterator;
/// taken from [bresenham-rs](https://github.com/mbr/bresenham-rs)
pub struct Bresenham {
@@ -127,7 +127,7 @@ impl Iterator for Bresenham {
}
}
-impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Draw a line from point a to point b.
///
/// Points not in bounds will not be included.
diff --git a/src/drawing/poly.rs b/src/drawing/poly.rs
index 3847a56..b73f321 100644
--- a/src/drawing/poly.rs
+++ b/src/drawing/poly.rs
@@ -2,12 +2,11 @@
use std::{
cmp::{max, min},
f32::consts::TAU,
- ops::DerefMut,
};
use crate::Image;
-impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Draws a filled polygon from a slice of points. Please close your poly. (first == last)
///
/// Borrowed from [imageproc](https://docs.rs/imageproc/latest/src/imageproc/drawing/polygon.rs.html#31), modified for less allocations.
diff --git a/src/drawing/tri.rs b/src/drawing/tri.rs
index c29ad1d..b50dfe4 100644
--- a/src/drawing/tri.rs
+++ b/src/drawing/tri.rs
@@ -1,9 +1,9 @@
//! trongle drawing
-use std::ops::DerefMut;
+
use crate::Image;
-impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Draw a (filled) triangle
/// ```
/// # use fimg::*;
diff --git a/src/lib.rs b/src/lib.rs
index 8049973..bb08357 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -233,7 +233,7 @@ impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
/// ```
pub const fn make<'a, const WIDTH: u32, const HEIGHT: u32>() -> Image<&'a [u8], CHANNELS>
where
- [(); CHANNELS * WIDTH as usize * HEIGHT as usize]: Sized,
+ [(); CHANNELS * WIDTH as usize * HEIGHT as usize]:,
{
Image {
width: NonZeroU32::new(WIDTH).expect("passed zero width to builder"),
@@ -243,7 +243,40 @@ impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
}
}
-impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+#[macro_export]
+/// Create a <code>[Image]<[[u8]; N], C></code> with ease. If your looking for a <code>[Image]<&'static [[u8]]></code>, try [`Image::make`].
+///
+/// ```
+/// let mut i = fimg::make!(4 channels 128 x 128);
+/// ```
+///
+/// Implementation note:
+/// This is doable with a const generic fn, but it returns a `fimg::Image<[u8; fimg::::{impl#7}::array::{constant#1}], _>` which means you cant actually type it, so its useless.
+macro_rules! make {
+ ($channels:literal channels $w:literal x $h: literal) => {
+ unsafe {
+ Image::<_, $channels>::new(
+ match ::core::num::NonZeroU32::new($w) {
+ Some(n) => n,
+ None => panic!("width is 0"),
+ },
+ match ::core::num::NonZeroU32::new($h) {
+ ::core::option::Option::Some(n) => n,
+ ::core::option::Option::None => panic!("height is 0"),
+ },
+ [0_u8; $channels * $w * $h],
+ )
+ }
+ };
+}
+
+impl<T: AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+ /// The size of the underlying buffer.
+ #[allow(clippy::len_without_is_empty)]
+ pub fn len(&self) -> usize {
+ self.buffer.as_ref().len()
+ }
+
/// # Safety
///
/// the output index is not guranteed to be in bounds
@@ -271,7 +304,7 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
};
// SAFETY: 🧐 is unsound? 😖
let index = unsafe { index.unchecked_mul(CHANNELS) };
- debug_assert!(self.buffer.len() > index);
+ debug_assert!(self.len() > index);
index
}
@@ -284,24 +317,24 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
/// Reference this image.
pub fn as_ref(&self) -> Image<&[u8], CHANNELS> {
// SAFETY: we got constructed okay, parameters must be valid
- unsafe { Image::new(self.width, self.height, &*self.buffer) }
+ unsafe { Image::new(self.width, self.height, self.buffer.as_ref()) }
}
#[inline]
/// Returns a iterator over every pixel
pub fn chunked(&self) -> impl DoubleEndedIterator<Item = &[u8; CHANNELS]> {
// SAFETY: 0 sized images illegal
- unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) };
+ unsafe { assert_unchecked!(self.len() > CHANNELS) };
// SAFETY: no half pixels!
- unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) };
- self.buffer.array_chunks::<CHANNELS>()
+ unsafe { assert_unchecked!(self.len() % CHANNELS == 0) };
+ self.buffer.as_ref().array_chunks::<CHANNELS>()
}
#[inline]
/// Flatten the chunks of this image into a slice of slices.
pub fn flatten(&self) -> &[[u8; CHANNELS]] {
// SAFETY: buffer cannot have half pixels
- unsafe { self.buffer.as_chunks_unchecked::<CHANNELS>() }
+ unsafe { self.buffer.as_ref().as_chunks_unchecked::<CHANNELS>() }
}
/// Return a pixel at (x, y).
@@ -312,13 +345,19 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
#[inline]
pub unsafe fn pixel(&self, x: u32, y: u32) -> [u8; CHANNELS] {
// SAFETY: x and y in bounds, slice is okay
- let ptr = unsafe { self.buffer.get_unchecked(self.slice(x, y)).as_ptr().cast() };
+ let ptr = unsafe {
+ self.buffer
+ .as_ref()
+ .get_unchecked(self.slice(x, y))
+ .as_ptr()
+ .cast()
+ };
// SAFETY: slice always returns a length of `CHANNELS`, so we `cast()` it for convenience.
unsafe { *ptr }
}
}
-impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// Return a mutable reference to a pixel at (x, y).
/// # Safety
///
@@ -329,30 +368,30 @@ impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANN
// SAFETY: we have been told x, y is in bounds.
let idx = self.slice(x, y);
// SAFETY: slice should always return a valid index
- unsafe { self.buffer.get_unchecked_mut(idx) }
+ unsafe { self.buffer.as_mut().get_unchecked_mut(idx) }
}
#[inline]
/// Returns a iterator over every pixel, mutably
pub fn chunked_mut(&mut self) -> impl Iterator<Item = &mut [u8; CHANNELS]> {
// SAFETY: 0 sized images are not allowed
- unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) };
+ unsafe { assert_unchecked!(self.len() > CHANNELS) };
// SAFETY: buffer cannot have half pixels
- unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) };
- self.buffer.array_chunks_mut::<CHANNELS>()
+ unsafe { assert_unchecked!(self.len() % CHANNELS == 0) };
+ self.buffer.as_mut().array_chunks_mut::<CHANNELS>()
}
/// Create a mutref to this image
pub fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
// SAFETY: construction went okay
- unsafe { Image::new(self.width, self.height, &mut self.buffer) }
+ unsafe { Image::new(self.width, self.height, self.buffer.as_mut()) }
}
#[inline]
/// Flatten the chunks of this image into a mutable slice of slices.
pub fn flatten_mut(&mut self) -> &mut [[u8; CHANNELS]] {
// SAFETY: buffer cannot have half pixels
- unsafe { self.buffer.as_chunks_unchecked_mut::<CHANNELS>() }
+ unsafe { self.buffer.as_mut().as_chunks_unchecked_mut::<CHANNELS>() }
}
/// # Safety
@@ -363,13 +402,13 @@ impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANN
unsafe fn copy_within(&mut self, src: std::ops::Range<usize>, dest: usize) {
let std::ops::Range { start, end } = src;
debug_assert!(
- dest <= self.buffer.len() - end - start,
+ dest <= self.buffer.as_ref().len() - end - start,
"dest is out of bounds"
);
#[allow(clippy::multiple_unsafe_ops_per_block)]
// SAFETY: the caller better be good
unsafe {
- let ptr = self.buffer.as_mut_ptr();
+ let ptr = self.buffer.as_mut().as_mut_ptr();
std::ptr::copy_nonoverlapping(ptr.add(start), ptr.add(dest), end - start)
};
}
@@ -399,7 +438,7 @@ impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
}
impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- /// Allocates a new image
+ /// Allocates a new image. If `width` and `height` are constant, try using [`make`].
///
/// # Panics
///
@@ -417,7 +456,7 @@ impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
/// helper macro for defining the save() method.
macro_rules! save {
($channels:literal == $clr:ident ($clrhuman:literal)) => {
- impl<T: std::ops::Deref<Target = [u8]>> Image<T, $channels> {
+ impl<T: AsRef<[u8]>> Image<T, $channels> {
#[cfg(feature = "save")]
#[doc = "Save this "]
#[doc = $clrhuman]
@@ -436,7 +475,7 @@ macro_rules! save {
(0.15000, 0.06000),
));
let mut writer = enc.write_header().unwrap();
- writer.write_image_data(&self.buffer).unwrap();
+ writer.write_image_data(self.buffer.as_ref()).unwrap();
}
}
};
diff --git a/src/overlay.rs b/src/overlay.rs
index 7f2715c..fca17bb 100644
--- a/src/overlay.rs
+++ b/src/overlay.rs
@@ -2,7 +2,6 @@
use crate::cloner::ImageCloner;
use super::{assert_unchecked, Image};
-use std::ops::{Deref, DerefMut};
use std::simd::{simd_swizzle, Simd, SimdInt, SimdPartialOrd};
/// Trait for layering a image ontop of another, with a offset to the second image.
@@ -100,7 +99,7 @@ unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
}
}
-impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> Overlay<Image<U, 4>> for Image<T, 4> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Image<T, 4> {
#[inline]
unsafe fn overlay(&mut self, with: &Image<U, 4>) -> &mut Self {
debug_assert!(self.width() == with.width());
@@ -108,7 +107,8 @@ impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> Overlay<Image<U, 4>> f
for (i, other_pixels) in with.chunked().enumerate() {
if other_pixels[3] >= 128 {
// SAFETY: outside are bounds of index from slice
- let own_pixels = unsafe { self.buffer.get_unchecked_mut(i * 4..i * 4 + 4) };
+ let own_pixels =
+ unsafe { self.buffer.as_mut().get_unchecked_mut(i * 4..i * 4 + 4) };
own_pixels.copy_from_slice(other_pixels);
}
}
@@ -127,7 +127,7 @@ impl ClonerOverlay<4, 4> for ImageCloner<'_, 4> {
}
}
-impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 4>> for Image<T, 3> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for Image<T, 3> {
#[inline]
unsafe fn overlay_at(&mut self, with: &Image<U, 4>, x: u32, y: u32) -> &mut Self {
// SAFETY: caller upholds this
@@ -142,9 +142,9 @@ impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 4>>
+ with.width() as usize)
* 3;
// SAFETY: index is in bounds
- let rgb = unsafe { self.buffer.get_unchecked_mut(o_x) };
+ let rgb = unsafe { self.buffer.as_mut().get_unchecked_mut(o_x) };
// SAFETY: bounds are outside index
- let rgba = unsafe { with.buffer.get_unchecked(i_x) };
+ let rgba = unsafe { with.buffer.as_ref().get_unchecked(i_x) };
// SAFETY: arguments are 🟢
unsafe { blit(rgb, rgba) }
}
@@ -163,7 +163,7 @@ impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> {
}
}
-impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 3>> for Image<T, 3> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 3>> for Image<T, 3> {
/// Overlay a RGB image(with) => self at coordinates x, y.
/// As this is a `RGBxRGB` operation, blending is unnecessary,
/// and this is simply a copy.
@@ -182,12 +182,12 @@ impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 3>>
..((j + y as usize) * self.width() as usize + x as usize + ($n as usize))
* 3;
// <= because ".." range
- debug_assert!(o_x.end <= self.buffer().len());
- debug_assert!(i_x.end <= with.buffer().len());
+ debug_assert!(o_x.end <= self.buffer().as_ref().len());
+ debug_assert!(i_x.end <= with.buffer().as_ref().len());
// SAFETY: bounds are ✅
- let a = unsafe { self.buffer.get_unchecked_mut(o_x) };
+ let a = unsafe { self.buffer.as_mut().get_unchecked_mut(o_x) };
// SAFETY: we are in ⬜!
- let b = unsafe { with.buffer.get_unchecked(i_x) };
+ let b = unsafe { with.buffer.as_ref().get_unchecked(i_x) };
a.copy_from_slice(b);
}
}};
@@ -202,19 +202,20 @@ impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 3>>
}
}
-impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> Overlay<Image<U, 4>> for Image<T, 3> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Image<T, 3> {
#[inline]
unsafe fn overlay(&mut self, with: &Image<U, 4>) -> &mut Self {
debug_assert!(self.width() == with.width());
debug_assert!(self.height() == with.height());
for (i, chunk) in with
.buffer
+ .as_ref()
.chunks_exact(with.width() as usize * 4)
.enumerate()
{
// SAFETY: all the bounds are good
let rgb = unsafe {
- self.buffer.get_unchecked_mut(
+ self.buffer.as_mut().get_unchecked_mut(
i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3,
)
};
@@ -236,7 +237,7 @@ impl ClonerOverlay<4, 3> for ImageCloner<'_, 3> {
}
}
-impl<T: DerefMut<Target = [u8]>, U: Deref<Target = [u8]>> OverlayAt<Image<U, 4>> for Image<T, 4> {
+impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for Image<T, 4> {
#[inline]
unsafe fn overlay_at(&mut self, with: &Image<U, 4>, x: u32, y: u32) -> &mut Self {
for j in 0..with.height() {