Closed seddonm1 closed 1 year ago
No. At this time the crate doesn't have such functionality. But you may create instance of DynamicImageViewMut
directly from pixels of destination image:
fn get_dst_view_with_padding(
pixels: &mut [U8x3],
width: usize,
height: usize,
top: usize,
bottom: usize,
left: usize,
right: usize,
) -> DynamicImageViewMut {
let rows: Vec<&mut [U8x3]> = pixels
.chunks_exact_mut(width)
.skip(top)
.take(height - top - bottom)
.map(|row| &mut row[left..width - right])
.collect();
let dst_width = NonZeroU32::new((width - left - right) as u32).unwrap();
let dst_height = NonZeroU32::new((height - top - bottom) as u32).unwrap();
let image_view = ImageViewMut::new(dst_width, dst_height, rows).unwrap();
image_view.into()
}
But, I think, you can't make a generic version of this function.
When I have free time, I will try to implement something like DynamicImageView::set_crop_box
but for DynamicImageViewMut
.
Great. Thanks @Cykooz I will test it this week.
i think it would be good to implement set_crop_box
as it may be useful for others or at least an example with padding could be good to build?
Thanks @Cykooz .
This is how I made it work but I needed to make Image::buffer_mut
pub
. Is there a reason not to have it public?
use std::fs::File;
use std::io::Write;
use std::num::NonZeroU32;
use fr::pixels::U8x3;
use fr::{DynamicImageViewMut, ImageViewMut};
use image::codecs::png::PngEncoder;
use image::io::Reader as ImageReader;
use image::{ColorType, ImageEncoder};
use fast_image_resize as fr;
fn main() {
// Read source image from file
let img = ImageReader::open("./data/nasa-4928x3279.png")
.unwrap()
.decode()
.unwrap();
let width = NonZeroU32::new(img.width()).unwrap();
let height = NonZeroU32::new(img.height()).unwrap();
let src_image =
fr::Image::from_vec_u8(width, height, img.to_rgb8().into_raw(), fr::PixelType::U8x3)
.unwrap();
// Create container for data of destination image
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(1024).unwrap();
let mut dst_image = fr::Image::new(dst_width, dst_height, src_image.pixel_type());
// Get mutable view of destination image data
let pixels = unsafe { dst_image.buffer_mut().align_to_mut::<U8x3>().1 };
let mut dst_view = get_dst_view_with_padding(
pixels,
dst_width.get() as usize,
dst_height.get() as usize,
300,
300,
0,
0,
);
// Create Resizer instance and resize source image
// into buffer of destination image
let mut resizer = fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::Bilinear));
resizer.resize(&src_image.view(), &mut dst_view).unwrap();
// Write destination image as PNG-file
let mut buffer = Vec::new();
PngEncoder::new(&mut buffer)
.write_image(
dst_image.buffer(),
dst_width.get(),
dst_height.get(),
ColorType::Rgb8,
)
.unwrap();
let mut output = File::create("output.png").unwrap();
output.write_all(&buffer).unwrap();
}
fn get_dst_view_with_padding(
pixels: &mut [U8x3],
width: usize,
height: usize,
top: usize,
bottom: usize,
left: usize,
right: usize,
) -> DynamicImageViewMut {
let rows: Vec<&mut [U8x3]> = pixels
.chunks_exact_mut(width)
.skip(top)
.take(height - top - bottom)
.map(|row| &mut row[left..width - right])
.collect();
let dst_width = NonZeroU32::new((width - left - right) as u32).unwrap();
let dst_height = NonZeroU32::new((height - top - bottom) as u32).unwrap();
let image_view = ImageViewMut::new(dst_width, dst_height, rows).unwrap();
image_view.into()
}
I've released version 2.7.0
Now you may do your task with help of new method DynamicImageViewMut::crop()
.
let mut dst_image = fr::Image::new(dst_width, dst_height, src_image.pixel_type());
let mut cropped_dst_view = dst_image.view_mut().crop(fr::CropBox {...}).unwrap();
...
resizer.resize(&src_image.view(), &mut cropped_dst_view).unwrap();
Excellent. Thanks @Cykooz
Hi, I know you have already implemented a
resize_image_with_cropping
method but do you have a good way toresize_with_pad
? I.e. resize but maintain input image proportions by applying a symmetric padding to the output image (aka. letterbox).Thanks