Implement image resizing

This commit is contained in:
Gergő Sályi 2023-04-26 23:22:46 +02:00
parent 9507d54585
commit a2471bda0b
2 changed files with 95 additions and 4 deletions

View file

@ -1,10 +1,12 @@
use std::{ use std::{
fs::read_dir, fs::read_dir,
num::NonZeroU32,
path::Path path::Path
}; };
use log::error; use fast_image_resize as fr;
use image::{ImageBuffer, Rgb, ImageError}; use image::{ImageBuffer, Rgb, ImageError};
use log::{debug, error};
use smithay_client_toolkit::shm::slot::{Buffer, SlotPool}; use smithay_client_toolkit::shm::slot::{Buffer, SlotPool};
use smithay_client_toolkit::reexports::client::protocol::wl_shm; use smithay_client_toolkit::reexports::client::protocol::wl_shm;
@ -16,6 +18,8 @@ pub fn workspace_bgs_from_output_image_dir(
format: wl_shm::Format, format: wl_shm::Format,
brightness: i32, brightness: i32,
contrast: f32, contrast: f32,
surface_width: NonZeroU32,
surface_height: NonZeroU32,
) )
-> Result<Vec<WorkspaceBackground>, String> -> Result<Vec<WorkspaceBackground>, String>
{ {
@ -72,7 +76,48 @@ pub fn workspace_bgs_from_output_image_dir(
image = image.brighten(brightness) image = image.brighten(brightness)
} }
let image = image.into_rgb8(); let mut image = image.into_rgb8();
let Some(image_width) = NonZeroU32::new(image.width()) else {
error!(
"Image '{}' has zero width, skipping", workspace_name
);
continue;
};
let Some(image_height) = NonZeroU32::new(image.height()) else {
error!(
"Image '{}' has zero height, skipping", workspace_name
);
continue;
};
if image_width != surface_width || image_height != surface_height
{
debug!("Resizing image '{}' from {}x{} to {}x{}",
workspace_name,
image_width, image_height,
surface_width, surface_height
);
let src_image = fr::Image::from_vec_u8(
image_width,
image_height,
image.into_raw(),
fr::PixelType::U8x3,
).unwrap();
let dst_image = resize_image_with_cropping(
src_image.view(),
surface_width,
surface_height,
);
image = ImageBuffer::from_raw(
surface_width.get(),
surface_height.get(),
dst_image.into_vec()
).unwrap();
}
let buffer = match format { let buffer = match format {
wl_shm::Format::Xrgb8888 => wl_shm::Format::Xrgb8888 =>
@ -142,3 +187,30 @@ fn buffer_bgr888_from_image(
buffer buffer
} }
// Copied example from fast_image_resize
fn resize_image_with_cropping(
mut src_view: fr::DynamicImageView,
dst_width: NonZeroU32,
dst_height: NonZeroU32
) -> fr::Image {
// Set cropping parameters
src_view.set_crop_box_to_fit_dst_size(dst_width, dst_height, None);
// Create container for data of destination image
let mut dst_image = fr::Image::new(
dst_width,
dst_height,
src_view.pixel_type(),
);
// Get mutable view of destination image data
let mut dst_view = dst_image.view_mut();
// Create Resizer instance and resize source image
// into buffer of destination image
let mut resizer = fr::Resizer::new(
fr::ResizeAlg::Convolution(fr::FilterType::Lanczos3)
);
resizer.resize(&src_view, &mut dst_view).unwrap();
dst_image
}

View file

@ -1,4 +1,4 @@
use std::path::PathBuf; use std::{num::NonZeroU32, path::PathBuf};
use log::{debug, error}; use log::{debug, error};
use smithay_client_toolkit::{ use smithay_client_toolkit::{
@ -160,6 +160,23 @@ impl OutputHandler for State {
output_name, width, height output_name, width, height
); );
if !width.is_positive() {
error!(
"New output '{}' has a non-positive width: {}, skipping",
output_name,
width
);
return;
}
if !height.is_positive() {
error!(
"New output '{}' has a non-positive height: {}, skipping",
output_name,
height
);
return;
}
let surface = self.compositor_state.create_surface(qh); let surface = self.compositor_state.create_surface(qh);
let layer = self.layer_shell.create_layer_surface( let layer = self.layer_shell.create_layer_surface(
@ -185,7 +202,9 @@ impl OutputHandler for State {
&mut self.shm_slot_pool, &mut self.shm_slot_pool,
pixel_format, pixel_format,
self.brightness, self.brightness,
self.contrast self.contrast,
NonZeroU32::new(width as u32).unwrap(),
NonZeroU32::new(height as u32).unwrap()
) { ) {
Ok(workspace_bgs) => { Ok(workspace_bgs) => {
debug!( debug!(