mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 02:28:19 -06:00
use AsRef instead of Deref
This commit is contained in:
parent
101ca55d29
commit
f465e25077
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "fimg"
|
||||
version = "0.4.13"
|
||||
version = "0.4.14"
|
||||
authors = ["bend-n <bend.n@outlook.com>"]
|
||||
license = "MIT"
|
||||
edition = "2021"
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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::*;
|
||||
|
|
81
src/lib.rs
81
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue