From d5d7b57e95e155690c2d188f624f951180b7d38f Mon Sep 17 00:00:00 2001 From: bendn Date: Tue, 23 Jan 2024 15:35:16 +0700 Subject: [PATCH] add uninit image overlay impls --- Cargo.toml | 2 +- src/overlay.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c7c6f1a..64af882 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.33" +version = "0.4.34" authors = ["bend-n "] license = "MIT" edition = "2021" diff --git a/src/overlay.rs b/src/overlay.rs index d2d6c85..9e79ad0 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -1,10 +1,10 @@ //! Handles image overlay // TODO Y/YA -use crate::cloner::ImageCloner; +use crate::{cloner::ImageCloner, uninit}; use super::{assert_unchecked, Image}; use crate::pixels::Blend; -use std::simd::prelude::*; +use std::{mem::transmute, simd::prelude::*}; /// Trait for layering a image ontop of another, with a offset to the second image. pub trait OverlayAt { @@ -181,6 +181,30 @@ impl + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt> for Im } } +impl> OverlayAt> for uninit::Image { + unsafe fn overlay_at(&mut self, with: &Image, x: u32, y: u32) -> &mut Self { + // SAFETY: caller upholds this + unsafe { assert_unchecked(x + with.width() <= self.width()) }; + debug_assert!(y + with.height() <= self.height()); + for j in 0..with.height() { + let i_x = j as usize * with.width() as usize * 4 + ..(j as usize + 1) * with.width() as usize * 4; + let o_x = ((j as usize + y as usize) * self.width() as usize + x as usize) * 3 + ..((j as usize + y as usize) * self.width() as usize + + x as usize + + with.width() as usize) + * 3; + // SAFETY: index is in bounds + let rgb = unsafe { transmute(self.buf().get_unchecked_mut(o_x)) }; + // SAFETY: bounds are outside index + let rgba = unsafe { with.buffer.as_ref().get_unchecked(i_x) }; + // SAFETY: arguments are 🟢 + unsafe { blit(rgb, rgba) } + } + self + } +} + impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> { #[inline] #[must_use = "function does not modify the original image"] @@ -192,6 +216,26 @@ impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> { } } +impl> OverlayAt> for uninit::Image { + #[inline] + unsafe fn overlay_at(&mut self, with: &Image, 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; + let o_x = ((j + y as usize) * self.width() as usize + x as usize) * 3 + ..((j + y as usize) * self.width() as usize + x as usize + (with.width() as usize)) + * 3; + // <= because ".." range + debug_assert!(o_x.end <= self.buffer().as_ref().len()); + debug_assert!(i_x.end <= with.buffer().as_ref().len()); + // SAFETY: we are in ⬜! + let b = unsafe { with.buffer.as_ref().get_unchecked(i_x) }; + // SAFETY: should work + unsafe { self.write(b, o_x) }; + } + self + } +} + impl + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt> for Image { /// Overlay a RGB image(with) => self at coordinates x, y. /// As this is a `RGBxRGB` operation, blending is unnecessary,