fast image operations
-rw-r--r--src/lib.rs6
-rw-r--r--src/overlay.rs11
2 files changed, 15 insertions, 2 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 0d78b6e..ebc35cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -149,6 +149,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");
@@ -306,6 +308,7 @@ 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 at(&self, x: u32, y: u32) -> usize {
(self.width(), self.height()).at::<CHANNELS>(x, y)
}
@@ -473,6 +476,7 @@ 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]>,
@@ -577,6 +581,7 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
/// - UB if x, y is out of bounds
/// - UB if buffer is too small
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
pub unsafe fn pixel_mut<U: Copy>(&mut self, x: u32, y: u32) -> &mut [U; CHANNELS]
where
T: AsMut<[U]> + AsRef<[U]>,
@@ -586,6 +591,7 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
}
/// Returns a mutable reference to a pixel at (x, y), if (x, y) is in bounds.
+ #[cfg_attr(debug_assertions, track_caller)]
pub fn get_pixel_mut<U>(&mut self, x: u32, y: u32) -> Option<&mut [U; CHANNELS]>
where
T: AsMut<[U]> + AsRef<[U]>,
diff --git a/src/overlay.rs b/src/overlay.rs
index f2bf0e6..2ab451b 100644
--- a/src/overlay.rs
+++ b/src/overlay.rs
@@ -29,6 +29,7 @@ pub trait ClonerOverlayAt<const W: usize, const C: usize>: Sealed {
/// # Safety
///
/// UB if x, y is out of bounds
+ #[must_use = "function does not modify the original image"]
unsafe fn overlay_at(&self, with: &Image<&[u8], W>, x: u32, y: u32) -> Image<Vec<u8>, C>;
}
@@ -113,6 +114,7 @@ unsafe fn blit(mut rgb: &mut [u8], mut rgba: &[u8]) {
impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Image<T, 4> {
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay(&mut self, with: &Image<U, 4>) -> &mut Self {
debug_assert!(self.width() == with.width());
debug_assert!(self.height() == with.height());
@@ -134,6 +136,7 @@ where
[u8; A]: Blend<B>,
{
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay_blended(&mut self, with: &Image<U, B>) -> &mut Self {
debug_assert!(self.width() == with.width());
debug_assert!(self.height() == with.height());
@@ -165,6 +168,7 @@ where
impl<T: AsMut<[u8]> + AsRef<[u8]>> Image<T, 3> {
#[doc(hidden)]
+ #[cfg_attr(debug_assertions, track_caller)]
pub unsafe fn blend_alpha_and_color_at(
&mut self,
with: &Image<&[u8], 1>,
@@ -195,6 +199,7 @@ impl ClonerOverlay<4, 4> for ImageCloner<'_, 4> {
impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for Image<T, 3> {
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay_at(&mut self, with: &Image<U, 4>, x: u32, y: u32) -> &mut Self {
// SAFETY: caller upholds this
unsafe { assert_unchecked(x + with.width() <= self.width()) };
@@ -219,6 +224,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for Im
}
impl<U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for uninit::Image<u8, 3> {
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay_at(&mut self, with: &Image<U, 4>, x: u32, y: u32) -> &mut Self {
// SAFETY: caller upholds this
unsafe { assert_unchecked(x + with.width() <= self.width()) };
@@ -244,7 +250,6 @@ impl<U: AsRef<[u8]>> OverlayAt<Image<U, 4>> for uninit::Image<u8, 3> {
impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> {
#[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>, 3> {
let mut new = self.dup();
// SAFETY: same
@@ -255,6 +260,7 @@ impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> {
impl<U: AsRef<[u8]>> OverlayAt<Image<U, 3>> for uninit::Image<u8, 3> {
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay_at(&mut self, with: &Image<U, 3>, x: u32, y: u32) -> &mut Self {
for j in 0..(with.width() as usize) {
let i_x = j * (with.width() as usize) * 3..(j + 1) * (with.width() as usize) * 3;
@@ -282,6 +288,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 3>> for Im
///
/// UB if x, y is out of bounds
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay_at(&mut self, with: &Image<U, 3>, x: u32, y: u32) -> &mut Self {
/// helper macro for defining rgb=>rgb overlays. allows unrolling
macro_rules! o3x3 {
@@ -321,7 +328,6 @@ impl ClonerOverlayAt<3, 3> for ImageCloner<'_, 3> {
///
/// UB if x, y is out of bounds
#[inline]
- #[must_use = "function does not modify the original image"]
unsafe fn overlay_at(&self, with: &Image<&[u8], 3>, x: u32, y: u32) -> Image<Vec<u8>, 3> {
let mut out = self.dup();
// SAFETY: same
@@ -332,6 +338,7 @@ impl ClonerOverlayAt<3, 3> for ImageCloner<'_, 3> {
impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Image<T, 3> {
#[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
unsafe fn overlay(&mut self, with: &Image<U, 4>) -> &mut Self {
debug_assert!(self.width() == with.width());
debug_assert!(self.height() == with.height());