mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
- 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:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user