diff --git a/client/src/cli.rs b/client/src/cli.rs index 67b93b2..22d97f7 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -212,6 +212,8 @@ pub enum ResizeStrategy { Crop, /// Resize the image to fit inside the screen, preserving the original aspect ratio Fit, + /// Resize the image to fit inside the screen, without preserving the original aspect ratio + Stretch, } #[derive(Parser)] diff --git a/client/src/imgproc.rs b/client/src/imgproc.rs index 86ef875..68c4333 100644 --- a/client/src/imgproc.rs +++ b/client/src/imgproc.rs @@ -205,6 +205,7 @@ pub fn compress_frames( ResizeStrategy::No => img_pad(&first_img, dim, color)?, ResizeStrategy::Crop => img_resize_crop(&first_img, dim, filter)?, ResizeStrategy::Fit => img_resize_fit(&first_img, dim, filter, color)?, + ResizeStrategy::Stretch => img_resize_stretch(&first_img, dim, filter)?, }; let mut canvas: Option> = None; @@ -217,6 +218,7 @@ pub fn compress_frames( ResizeStrategy::No => img_pad(&img, dim, color)?, ResizeStrategy::Crop => img_resize_crop(&img, dim, filter)?, ResizeStrategy::Fit => img_resize_fit(&img, dim, filter, color)?, + ResizeStrategy::Stretch => img_resize_stretch(&img, dim, filter)?, }; if let Some(canvas) = canvas.as_ref() { @@ -382,6 +384,45 @@ pub fn img_resize_fit( } } +pub fn img_resize_stretch( + img: &Image, + dimensions: (u32, u32), + filter: FilterType, +) -> Result, String> { + let (width, height) = dimensions; + let resized_img = if (img.width, img.height) != (width, height) { + let pixel_type = if img.format.channels() == 3 { + PixelType::U8x3 + } else { + PixelType::U8x4 + }; + + let src = match fast_image_resize::images::ImageRef::new( + img.width, + img.height, + img.bytes.as_ref(), + pixel_type, + ) { + Ok(i) => i, + Err(e) => return Err(e.to_string()), + }; + + let mut dst = fast_image_resize::images::Image::new(width, height, pixel_type); + let mut resizer = Resizer::new(); + let options = ResizeOptions::new().resize_alg(ResizeAlg::Convolution(filter)); + + if let Err(e) = resizer.resize(&src, &mut dst, Some(&options)) { + return Err(e.to_string()); + } + + dst.into_vec().into_boxed_slice() + } else { + img.bytes.clone() + }; + + Ok(resized_img) +} + pub fn img_resize_crop( img: &Image, dimensions: (u32, u32), diff --git a/client/src/main.rs b/client/src/main.rs index a284cba..f4d7712 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -184,6 +184,9 @@ fn make_img_request( ResizeStrategy::Fit => { img_resize_fit(&img_raw, dim, make_filter(&img.filter), &img.fill_color)? } + ResizeStrategy::Stretch => { + img_resize_stretch(&img_raw, dim, make_filter(&img.filter))? + } }; img_req_builder.push( diff --git a/doc/swww-img.1.scd b/doc/swww-img.1.scd index 8df9f35..c9e40eb 100644 --- a/doc/swww-img.1.scd +++ b/doc/swww-img.1.scd @@ -40,9 +40,10 @@ swww-img Whether to resize the image and the method by which to resize it. Possible values: - - _no_: Do not resize the image - - _crop_: Resize the image to fill the whole screen, cropping out parts that don't fit - - _fit_: Resize the image to fit inside the screen, preserving the original aspect ratio + - _no_: Do not resize the image + - _crop_: Resize the image to fill the whole screen, cropping out parts that don't fit + - _fit_: Resize the image to fit inside the screen, preserving the original aspect ratio + - _stretch_: Resize the image to fit inside the screen, without preserving the original aspect ratio Default is _crop_.