Add scaling mode "Fill"
- Image covers the entire screen - Aspect ratio preserved - Excess image cropped (centered)
This commit is contained in:
parent
f95ff94dfc
commit
84186d3d66
@ -1,11 +1,11 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{args, config};
|
use crate::{args, config, wallpaper};
|
||||||
|
|
||||||
pub struct WallpaperSettings {
|
pub struct WallpaperSettings {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub mode: crate::wallpaper::ScalingMode,
|
pub mode: wallpaper::ScalingMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_wallpaper(
|
pub fn resolve_wallpaper(
|
||||||
@ -50,7 +50,8 @@ pub fn resolve_wallpaper(
|
|||||||
_ => unreachable!(),
|
_ => 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 })
|
Ok(WallpaperSettings { path, mode })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,11 @@ use std::path::Path;
|
|||||||
|
|
||||||
/// Supported wallpaper scaling modes.
|
/// Supported wallpaper scaling modes.
|
||||||
///
|
///
|
||||||
/// Only `Stretch` is implemented for now.
|
|
||||||
/// Others are defined so the public API does not need to change later.
|
/// Others are defined so the public API does not need to change later.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ScalingMode {
|
pub enum ScalingMode {
|
||||||
Stretch,
|
Stretch,
|
||||||
// Fill,
|
Fill,
|
||||||
// Fit,
|
// Fit,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +37,40 @@ fn rgba_to_bgra(mut pixels: Vec<u8>) -> Vec<u8> {
|
|||||||
pixels
|
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:
|
/// Stretch mode:
|
||||||
/// - Image is resized to exactly match screen dimensions
|
/// - Image is resized to exactly match screen dimensions
|
||||||
/// - Aspect ratio is not preserved
|
/// - Aspect ratio is not preserved
|
||||||
@ -85,6 +118,7 @@ pub fn prepare_wallpaper(
|
|||||||
|
|
||||||
let prepared = match mode {
|
let prepared = match mode {
|
||||||
ScalingMode::Stretch => prepare_stretch(&img, screen_width, screen_height),
|
ScalingMode::Stretch => prepare_stretch(&img, screen_width, screen_height),
|
||||||
|
ScalingMode::Fill => prepare_fill(&img, screen_width, screen_height),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(prepared)
|
Ok(prepared)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user