From 84186d3d66e7173fefa04e43e950246bf5bdff87 Mon Sep 17 00:00:00 2001 From: candifloss Date: Thu, 18 Dec 2025 11:08:16 +0530 Subject: [PATCH] Add scaling mode "Fill" - Image covers the entire screen - Aspect ratio preserved - Excess image cropped (centered) --- src/settings.rs | 7 ++++--- src/wallpaper.rs | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index 1ec1865..ec8dcc0 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -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 }) } diff --git a/src/wallpaper.rs b/src/wallpaper.rs index 59bfb21..8910d1b 100644 --- a/src/wallpaper.rs +++ b/src/wallpaper.rs @@ -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) -> Vec { 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)