Add scaling mode "Fill"

- Image covers the entire screen
- Aspect ratio preserved
- Excess image cropped (centered)
This commit is contained in:
Candifloss 2025-12-18 11:08:16 +05:30
parent f95ff94dfc
commit 84186d3d66
2 changed files with 40 additions and 5 deletions

View File

@ -1,11 +1,11 @@
use anyhow::Result;
use std::path::PathBuf;
use crate::{args, config};
use crate::{args, config, wallpaper};
pub struct WallpaperSettings {
pub path: PathBuf,
pub mode: crate::wallpaper::ScalingMode,
pub mode: wallpaper::ScalingMode,
}
pub fn resolve_wallpaper(
@ -50,7 +50,8 @@ pub fn resolve_wallpaper(
_ => unreachable!(),
};
let mode = crate::wallpaper::ScalingMode::Stretch; // Default for now. Fix later
//let mode = wallpaper::ScalingMode::Stretch; //
let mode = wallpaper::ScalingMode::Fill; // Default
Ok(WallpaperSettings { path, mode })
}

View File

@ -4,12 +4,11 @@ use std::path::Path;
/// Supported wallpaper scaling modes.
///
/// Only `Stretch` is implemented for now.
/// Others are defined so the public API does not need to change later.
#[derive(Debug, Clone, Copy)]
pub enum ScalingMode {
Stretch,
// Fill,
Fill,
// Fit,
}
@ -38,6 +37,40 @@ fn rgba_to_bgra(mut pixels: Vec<u8>) -> Vec<u8> {
pixels
}
/// Fill mode:
/// - Image covers the entire screen
/// - Aspect ratio is preserved
/// - Excess image is cropped (centered)
fn prepare_fill(img: &RgbaImage, screen_width: u32, screen_height: u32) -> PreparedWallpaper {
let img_w = img.width() as f32;
let img_h = img.height() as f32;
let screen_w = screen_width as f32;
let screen_h = screen_height as f32;
// Scale so that BOTH dimensions cover the screen
let scale = (screen_w / img_w).max(screen_h / img_h);
let scaled_w = (img_w * scale).round() as u32;
let scaled_h = (img_h * scale).round() as u32;
let resized = imageops::resize(img, scaled_w, scaled_h, imageops::FilterType::Lanczos3);
// Center the image; negative offsets cause cropping
let offset_x = (screen_width as i32 - scaled_w as i32) / 2;
let offset_y = (screen_height as i32 - scaled_h as i32) / 2;
let pixels = rgba_to_bgra(resized.into_raw());
PreparedWallpaper {
pixels,
width: scaled_w,
height: scaled_h,
offset_x,
offset_y,
}
}
/// Stretch mode:
/// - Image is resized to exactly match screen dimensions
/// - Aspect ratio is not preserved
@ -85,6 +118,7 @@ pub fn prepare_wallpaper(
let prepared = match mode {
ScalingMode::Stretch => prepare_stretch(&img, screen_width, screen_height),
ScalingMode::Fill => prepare_fill(&img, screen_width, screen_height),
};
Ok(prepared)