- Added method DynamicImageViewMut::crop() to create cropped version of ImageViewMut.

- Added method `ImageViewMut::crop()` to create cropped version of `ImageViewMut`.
This commit is contained in:
Kirill Kuzminykh
2023-03-24 23:40:25 +03:00
parent a3692f11b6
commit fd071fd0cc
4 changed files with 96 additions and 9 deletions
+8
View File
@@ -1,3 +1,11 @@
## [Unreleased] - ReleaseDate
### Crate
- Added method `DynamicImageViewMut::crop()` to create cropped version of `ImageViewMut`
([#13](https://github.com/Cykooz/fast_image_resize/issues/13)).
- Added method `ImageViewMut::crop()` to create cropped version of `ImageViewMut`.
## [2.6.0] - 2023-03-01
### Crate
+5
View File
@@ -146,6 +146,11 @@ impl<'a> DynamicImageViewMut<'a> {
pub fn pixel_type(&self) -> PixelType {
dynamic_mut_map!(self, |typed_image| typed_image.pixel_type())
}
/// Create cropped version of the view.
pub fn crop(self, crop_box: CropBox) -> Result<Self, CropBoxError> {
Ok(dynamic_mut_map!(self, typed_image => typed_image.crop(crop_box)?))
}
}
macro_rules! from_typed {
+25
View File
@@ -388,6 +388,31 @@ where
.for_each(|(d, s)| d.copy_from_slice(s));
Ok(())
}
/// Create cropped version of the view.
pub fn crop(self, crop_box: CropBox) -> Result<Self, CropBoxError> {
if crop_box.left >= self.width.get() || crop_box.top >= self.height.get() {
return Err(CropBoxError::PositionIsOutOfImageBoundaries);
}
let right = crop_box.left + crop_box.width.get();
let bottom = crop_box.top + crop_box.height.get();
if right > self.width.get() || bottom > self.height.get() {
return Err(CropBoxError::SizeIsOutOfImageBoundaries);
}
let row_range = (crop_box.left as usize)..=(right as usize);
let rows = self
.rows
.into_iter()
.skip(crop_box.top as usize)
.take(crop_box.height.get() as usize)
.map(|row| unsafe { row.get_unchecked_mut(row_range.clone()) })
.collect();
Ok(Self {
width: crop_box.width,
height: crop_box.height,
rows,
})
}
}
impl<'a, P> From<ImageViewMut<'a, P>> for ImageView<'a, P>
+58 -9
View File
@@ -1,11 +1,11 @@
use fast_image_resize as fr;
use fast_image_resize::pixels::U8;
use std::num::NonZeroU32;
use testing::nonzero;
#[test]
fn create_image_from_small_buffer() {
let width = NonZeroU32::new(64).unwrap();
let height = NonZeroU32::new(32).unwrap();
let width = nonzero(64);
let height = nonzero(32);
let mut buffer = vec![0; 64 * 30];
let res = fr::Image::from_slice_u8(width, height, &mut buffer, fr::PixelType::U8);
@@ -17,8 +17,8 @@ fn create_image_from_small_buffer() {
#[test]
fn create_image_view_from_small_buffer() {
let width = NonZeroU32::new(64).unwrap();
let height = NonZeroU32::new(32).unwrap();
let width = nonzero(64);
let height = nonzero(32);
let mut buffer = vec![0; 64 * 30];
let res = fr::ImageViewMut::<U8>::from_buffer(width, height, &mut buffer);
@@ -30,8 +30,8 @@ fn create_image_view_from_small_buffer() {
#[test]
fn create_image_from_big_buffer() {
let width = NonZeroU32::new(64).unwrap();
let height = NonZeroU32::new(32).unwrap();
let width = nonzero(64);
let height = nonzero(32);
let mut buffer = vec![0; 65 * 32];
let res = fr::Image::from_slice_u8(width, height, &mut buffer, fr::PixelType::U8);
@@ -43,8 +43,8 @@ fn create_image_from_big_buffer() {
#[test]
fn create_image_view_from_big_buffer() {
let width = NonZeroU32::new(64).unwrap();
let height = NonZeroU32::new(32).unwrap();
let width = nonzero(64);
let height = nonzero(32);
let mut buffer = vec![0; 65 * 32];
let res = fr::ImageViewMut::<U8>::from_buffer(width, height, &mut buffer);
@@ -53,3 +53,52 @@ fn create_image_view_from_big_buffer() {
let res = fr::ImageView::<U8>::from_buffer(width, height, &buffer);
assert!(res.is_ok());
}
#[test]
fn crop_view_mut() {
// White source image
let src_image = fr::Image::from_vec_u8(
nonzero(64),
nonzero(32),
vec![255; 64 * 32],
fr::PixelType::U8,
)
.unwrap();
// Black destination image
let mut dst_image = fr::Image::new(nonzero(64), nonzero(32), fr::PixelType::U8);
let mut cropped_dst_view = dst_image
.view_mut()
.crop(fr::CropBox {
left: 10,
top: 10,
width: nonzero(44),
height: nonzero(12),
})
.unwrap();
assert_eq!(cropped_dst_view.width().get(), 44);
assert_eq!(cropped_dst_view.height().get(), 12);
let mut resizer = fr::Resizer::new(fr::ResizeAlg::Nearest);
resizer
.resize(&src_image.view(), &mut cropped_dst_view)
.unwrap();
let row_size: usize = 64;
let dst_buffer = dst_image.buffer();
let black_block = vec![0u8; 10 * row_size];
// Top border
assert_eq!(dst_buffer[0..10 * row_size], black_block);
// Middle rows
let mut middle_row = vec![0u8; 10];
middle_row.extend(vec![255u8; 44]);
middle_row.extend(vec![0u8; 10]);
for row in dst_buffer.chunks_exact(row_size).skip(10).take(12) {
assert_eq!(row, middle_row);
}
// Bottom border
assert_eq!(dst_buffer[22 * row_size..], black_block);
}