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
Show less
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)
+}
+
...
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_rgb = remove_duplicates(collect_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_rgb.sort_by(|a, b| {
@@ -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_rgb[20];
- (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_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 "{script}""
));
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