use zune_core::bit_depth::BitType;
use zune_image::channel::Channel;
use zune_image::errors::ImageErrors;
use zune_image::image::Image;
use zune_image::traits::OperationsTrait;
pub struct Crop {
x: usize,
y: usize,
width: usize,
height: usize
}
impl Crop {
#[must_use]
pub fn new(width: usize, height: usize, x: usize, y: usize) -> Crop {
Crop {
x,
y,
width,
height
}
}
}
impl OperationsTrait for Crop {
fn name(&self) -> &'static str {
"Crop"
}
fn execute_impl(&self, image: &mut Image) -> Result<(), ImageErrors> {
let new_dims = self.width * self.height * image.depth().size_of();
let (old_width, _) = image.dimensions();
let depth = image.depth().bit_type();
for channel in image.channels_mut(false) {
let mut new_vec = Channel::new_with_length_and_type(new_dims, channel.get_type_id());
match depth {
BitType::U8 => {
crop::<u8>(
channel.reinterpret_as()?,
old_width,
new_vec.reinterpret_as_mut()?,
self.width,
self.height,
self.x,
self.y
);
}
BitType::U16 => {
crop::<u16>(
channel.reinterpret_as()?,
old_width,
new_vec.reinterpret_as_mut()?,
self.width,
self.height,
self.x,
self.y
);
}
BitType::F32 => {
crop::<f32>(
channel.reinterpret_as()?,
old_width,
new_vec.reinterpret_as_mut()?,
self.width,
self.height,
self.x,
self.y
);
}
d => return Err(ImageErrors::ImageOperationNotImplemented(self.name(), d))
}
*channel = new_vec;
}
image.set_dimensions(self.width, self.height);
Ok(())
}
fn supported_types(&self) -> &'static [BitType] {
&[BitType::U8, BitType::U16, BitType::F32]
}
}
pub fn crop<T: Copy>(
in_image: &[T], in_width: usize, out_image: &mut [T], out_width: usize, out_height: usize,
x: usize, y: usize
) {
if in_width == 0 || out_width == 0 {
return;
}
for (single_in_width, single_out_width) in in_image
.chunks_exact(in_width)
.skip(y)
.take(out_height)
.zip(out_image.chunks_exact_mut(out_width))
{
single_out_width.copy_from_slice(&single_in_width[x..x + out_width]);
}
}
#[cfg(feature = "benchmarks")]
#[cfg(test)]
mod benchmarks {
extern crate test;
use crate::crop::crop;
#[bench]
fn crop_bench(b: &mut test::Bencher) {
let width = 800;
let height = 800;
let dimensions = width * height;
let c1 = vec![0_u16; dimensions];
let mut c2 = vec![0_u16; dimensions / 4];
b.iter(|| {
crop(&c1, width, &mut c2, width / 2, height / 2, 0, 0);
});
}
}