Pi66

Home | Repos | About | Blog | Gaza

walrs
pywal but if its Fast-Minimal-Simple
git clone https://git.pi66.xyz/walrs

About | Files | Commits | Refs | License


Fix: make palette prettier and add more control over wallpaper and scripts

Author: pixel2175
Date: 2025-06-23 22:28
commit: 73eff85f

Stat

M src/get_colors.rs 180 +62 -118
M src/reload.rs 2 +1 -1
M src/wallpaper.rs 6 +1 -5

Diff

diff --git a/src/get_colors.rs b/src/get_colors.rs
index 9a28a56..6243a3b 100644
--- a/src/get_colors.rs
+++ b/src/get_colors.rs
@@ -1,6 +1,5 @@
 use crate::utils::warning;
 use color_thief::ColorFormat;
-use image::RgbaImage;
 use kmeans_colors::get_kmeans;
 use palette::{FromColor, IntoColor, Lab, Srgb};
 use palette_extract::{MaxColors, Quality};
@@ -32,152 +31,97 @@ fn to_gray(r: u8, g: u8, b: u8, v: u8) -> (u8, u8, u8) {
     (gray, gray, gray)
 }

-fn kmeans_colors(len: u8, native_rgba: &RgbaImage) -> Vec<(u8, u8, u8)> { +fn generate_variation(color: (u8, u8, u8), offset: i8) -> (u8, u8, u8) { + adjust_rgb(color.0, color.1, color.2, offset, 50) +} + ...

Show all

diff --git a/src/get_colors.rs b/src/get_colors.rs
index 9a28a56..6243a3b 100644
--- a/src/get_colors.rs
+++ b/src/get_colors.rs
@@ -1,6 +1,5 @@
 use crate::utils::warning;
 use color_thief::ColorFormat;
-use image::RgbaImage;
 use kmeans_colors::get_kmeans;
 use palette::{FromColor, IntoColor, Lab, Srgb};
 use palette_extract::{MaxColors, Quality};
@@ -32,152 +31,97 @@ fn to_gray(r: u8, g: u8, b: u8, v: u8) -> (u8, u8, u8) {
     (gray, gray, gray)
 }

-fn kmeans_colors(len: u8, native_rgba: &RgbaImage) -> Vec<(u8, u8, u8)> { +fn generate_variation(color: (u8, u8, u8), offset: i8) -> (u8, u8, u8) { + adjust_rgb(color.0, color.1, color.2, offset, 50) +} + +pub fn get_colors( + image_path: &str, + send: bool, + brightness: Option<i8>, + saturation: Option<i8>, +) -> (Vec<(u8, u8, u8)>, u8) { + let core_image = match image::open(image_path) { + Ok(img) => img, + Err(_) => { + let data = read(image_path).unwrap(); + match image::guess_format(&data) { + Ok(fmt) => image::load_from_memory_with_format(&data, fmt).unwrap(), + Err(_) => { + warning("Image", "Unsupported or corrupted image format", send); + exit(1); + } + } + } + }; + + // resize the image + let image = core_image.resize( + 400, + (core_image.height() as f32 * (400 as f32 / core_image.width() as f32)) as u32, + image::imageops::FilterType::Lanczos3, + ); + + let native_rgba = image.to_rgba8(); + let alpha = &native_rgba.get_pixel(0, 0)[3]; + let mut collect_rgb: Vec<(u8, u8, u8)> = Vec::new(); + let pixels_kmeans: Vec<Lab> = native_rgba .pixels() .filter(|p| p.0[3] > 0) // Filter out transparent pixels .map(|p| { - // Convert RGBA to Srgb (ignore alpha for clustering) let srgb = Srgb::new( p.0[0] as f32 / 255.0, p.0[1] as f32 / 255.0, p.0[2] as f32 / 255.0, ) .into_linear(); - // Convert to LAB for perceptual accuracy srgb.into_color() }) .collect();

- let palette_kmeans: Vec<Srgb> = get_kmeans(10, len as usize, 1.0, false, &pixels_kmeans, 0) + let palette_kmeans: Vec<Srgb> = get_kmeans(10, 20, 1.0, false, &pixels_kmeans, 0) .centroids .iter() .map(|&lab| Srgb::from_color(lab)) .collect();

- palette_kmeans - .iter() - .map(|color| { - let (r, g, b) = ( - (color.red * 255.0).round() as u8, - (color.green * 255.0).round() as u8, - (color.blue * 255.0).round() as u8, - ); - (r, g, b) - }) - .collect::<Vec<(u8, u8, u8)>>() -} + for color in &palette_kmeans { + let (r, g, b) = ( + (color.red * 255.0).round() as u8, + (color.green * 255.0).round() as u8, + (color.blue * 255.0).round() as u8, + ); + collect_rgb.push((r, g, b)) + }

-fn color_thief_colors(len: u8, native_rgba: &RgbaImage) -> Vec<(u8, u8, u8)> { let palette_extract = palette_extract::get_palette_with_options( - native_rgba, + &native_rgba, palette_extract::PixelEncoding::Rgba, Quality::new(5), - MaxColors::new(len), + MaxColors::new(10), palette_extract::PixelFilter::White, ); + let palette_thief = color_thief::get_palette(&native_rgba, ColorFormat::Rgba, 5, 10);

- palette_extract - .iter() - .map(|color| (color.r, color.g, color.b)) - .collect::<Vec<(u8, u8, u8)>>() -} - -fn palette_extract_colors(len: u8, native_rgba: &RgbaImage, send: bool) -> Vec<(u8, u8, u8)> { - let palette_thief = color_thief::get_palette(native_rgba, ColorFormat::Rgba, 5, len) - .unwrap_or_else(|_| { - warning("Backend", "palette thief can't extract the palette", send); - exit(1) - }); - - palette_thief - .iter() - .map(|color| (color.r, color.g, color.b)) - .collect::<Vec<(u8, u8, u8)>>() -} - -fn extract_colors( - len: u8, - backend: &str, - native_rgba: &RgbaImage, - send: bool, -) -> Vec<(u8, u8, u8)> { - match backend { - "backends" => { - println!( - "┌──────────────────────┬───────────────────────┐ -│ Method │ Description │ -├──────────────────────┼───────────────────────┤ -│ kmeans │ best colors, slow │ -│ color_thief │ balanced │ -│ palette_extract │ fast, weak colors │ -│ all │ use all methods │ -└──────────────────────┴───────────────────────┘" - ); - exit(0) - } - "kmeans" => kmeans_colors(10, native_rgba), - "color_thief" => color_thief_colors(10, native_rgba), - "palette_extract" => palette_extract_colors(10, native_rgba, send), - "all" => { - let mut collected: Vec<(u8, u8, u8)> = Vec::new(); - kmeans_colors(len - 2, native_rgba).iter().for_each(|c| { - collected.push(*c); - }); - color_thief_colors(len / 3_u8 + 2, native_rgba) - .iter() - .for_each(|c| { - collected.push(*c); - }); - palette_extract_colors(len / 3_u8 + 2, native_rgba, send) - .iter() - .for_each(|c| { - collected.push(*c); - }); - - collected - } - &_ => { - warning("Backend", "this backend is not exists", send); - exit(1) - } + for color in &palette_extract { + collect_rgb.push((color.r, color.g, color.b)); } -}

-pub fn get_colors( - image_path: &str, - backend: &str, - send: bool, - brightness: Option<i8>, - saturation: Option<i8>, -) -> (Vec<(u8, u8, u8)>, u8) { - let core_image = match image::open(image_path) { - Ok(img) => img, - Err(_) => { - let data = read(image_path).unwrap(); - match image::guess_format(&data) { - Ok(fmt) => image::load_from_memory_with_format(&data, fmt).unwrap(), - Err(_) => { - warning("Image", "Unsupported or corrupted image format", send); - exit(1) - } - } + if let Ok(ref colors) = palette_thief { + for color in colors { + collect_rgb.push((color.r, color.g, color.b)); } - }; - - let image = core_image.resize( - 250, - (core_image.height() as f32 * (250_f32 / core_image.width() as f32)) as u32, - image::imageops::FilterType::Lanczos3, - ); - - let native_rgba = image.to_rgba8(); - let alpha = &native_rgba.get_pixel(0, 0)[3]; - let mut collect_rgb: Vec<(u8, u8, u8)> = extract_colors(30, backend, &native_rgba, send); + }

 collect&#95;rgb = remove&#95;duplicates(collect&#95;rgb);

+ + let mut i = 0; while collect_rgb.len() <= 21 { - collect_rgb.push(extract_colors(1, backend, &native_rgba, send)[0]); + let base = collect_rgb[i % collect_rgb.len()]; + let variation = generate_variation(base, 10 * (i as i8 + 1)); + collect_rgb.push(variation); + i += 1; }

 collect&#95;rgb.sort&#95;by(&#124;a, b&#124; {

@@ -196,15 +140,15 @@ pub fn get_colors( r, g, b, - brightness.unwrap_or(0) - 5, + brightness.unwrap_or(0) - 15, saturation.unwrap_or(0) + 80, ); done.push((r, g, b)); }

 let (mut r, mut g, mut b) = collect&#95;rgb&#91;20&#93;;

- (r, g, b) = adjust_rgb(r, g, b, 45, 65); - (r, g, b) = to_gray(r, g, b, 25); + (r, g, b) = adjust_rgb(r, g, b, 40, 60); + (r, g, b) = to_gray(r, g, b, 15); done[7] = (r, g, b); done[15] = (r, g, b);

diff --git a/src/reload.rs b/src/reload.rs index 77fbdb4..adbb008 100644 --- a/src/reload.rs +++ b/src/reload.rs @@ -72,7 +72,7 @@ pub fn reload(send: bool, set_wal: bool, run_scripts: bool) {

 // applie the wallpaper
 if !set&#95;wal {

- change_wallpaper(&get_wallpaper(&cache, send), send); + change_wallpaper(&get_wallpaper(&cache.clone(), send.clone()), send.clone()) }

 // change terminal colors

diff --git a/src/wallpaper.rs b/src/wallpaper.rs index f0002c9..8ee2083 100644 --- a/src/wallpaper.rs +++ b/src/wallpaper.rs @@ -230,11 +230,7 @@ fn set_desktop_wallpaper(d: &str, img: &str, send: bool) { "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript &#34;{script}&#34;" )); info("Wallpaper", "wallpaper set with KDE Plasma settings", send); - } else if d.contains("i3") { - set_wm_wallpaper(&abs_path, send); - } else if d.contains("bspwm") { - set_wm_wallpaper(&abs_path, send); - } else if d.contains("qtile") { + } else if d.contains("i3") || d.contains("bspwm") || d.contains("qtile") { set_wm_wallpaper(&abs_path, send); } else if d.contains("wayland") { // Generic Wayland - try multiple approaches

// Created by Pi66

// Copyright ©Pi66 2026