From 6ccc8606ef9e4225dec67394368b67ab6750ba1f Mon Sep 17 00:00:00 2001 From: nicholai Date: Mon, 8 Sep 2025 04:42:01 -0600 Subject: [PATCH] first push of scripts --- pywal/pywal-openrgb.py | 30 ++++++++ pywal/pywal16.sh | 22 ++++++ pywal/update-waybar-theme.sh | 16 +++++ pywal/wallpapermenu.sh | 23 +++++++ sort_images_by_color.py | 130 +++++++++++++++++++++++++++++++++++ wallpapersync.sh | 11 +++ 6 files changed, 232 insertions(+) create mode 100644 pywal/pywal-openrgb.py create mode 100755 pywal/pywal16.sh create mode 100755 pywal/update-waybar-theme.sh create mode 100755 pywal/wallpapermenu.sh create mode 100644 sort_images_by_color.py create mode 100755 wallpapersync.sh diff --git a/pywal/pywal-openrgb.py b/pywal/pywal-openrgb.py new file mode 100644 index 0000000..6b674da --- /dev/null +++ b/pywal/pywal-openrgb.py @@ -0,0 +1,30 @@ +import json +from openrgb import OpenRGBClient +from openrgb.utils import RGBColor + +# Path to Pywal's colors.json +colors_file = '/home/Nicholai/.cache/wal/colors.json' + +# Load Pywal colors +with open(colors_file, 'r') as f: + colors = json.load(f) + +# Extract the first color from Pywal's palette +primary_color_hex = colors['colors']['color3'] + +import subprocess + +# Remove the '#' prefix from the hex color +primary_color_hex_no_prefix = primary_color_hex.lstrip('#') + +# Construct the command with the modified hex color +command = ["openrgb", "--color", primary_color_hex_no_prefix] + +# Execute the command +try: + subprocess.run(command, check=True) + print(f"Successfully set OpenRGB color to {primary_color_hex_no_prefix}") +except subprocess.CalledProcessError as e: + print(f"Error setting OpenRGB color: {e}") +except FileNotFoundError: + print("Error: 'openrgb' command not found. Make sure OpenRGB is installed and in your PATH.") diff --git a/pywal/pywal16.sh b/pywal/pywal16.sh new file mode 100755 index 0000000..e15061f --- /dev/null +++ b/pywal/pywal16.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +#update waybar +cp "~/.cache/wal/colors-waybar.css" "~/.config/waybar/" + +#killall -SIGUSR2 waybar +#waybar + +#update oomox +#cp "~/.cache/wal/colors-oomox" " +nwg-look -x + +#refresh qutebrowser if running +pgrep qutebrowser > /dev/null && qutebrowser ':config-source' + +notify-send "Wallpaper and colorscheme changed, setting RGB value" + +#run walcord +walcord + +#set RGB last so it doesn't hang +python /home/Nicholai/scripts/pywal/pywal-openrgb.py diff --git a/pywal/update-waybar-theme.sh b/pywal/update-waybar-theme.sh new file mode 100755 index 0000000..44cf292 --- /dev/null +++ b/pywal/update-waybar-theme.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Check if an image path is provided +if [ -z "$1" ]; then + echo "Usage: $0 /path/to/image" + exit 1 +fi + +# Run pywal to generate the color scheme +wal -i "$1" + +# Copy the generated Waybar CSS to your .config directory +cp "${HOME}/.cache/wal/colors-waybar.css" "${HOME}/.config/waybar/" + +# Reload Waybar to apply the new theme +killall -SIGUSR2 waybar diff --git a/pywal/wallpapermenu.sh b/pywal/wallpapermenu.sh new file mode 100755 index 0000000..c5bba8b --- /dev/null +++ b/pywal/wallpapermenu.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +FOLDER=~/Pictures/Wallpapers +SCRIPT=~/scripts/pywal/pywal16.sh + +menu() { + CHOICE=$(nsxiv -otb $FOLDER/*) # nsxiv -o writes filename to stdout + +case $CHOICE in + *.*) wal -i "$CHOICE" -o $SCRIPT + killall swaybg + swaybg -m fill -i "$CHOICE";; + *) exit 0 ;; +esac +} + +case "$#" in + 0) menu;; + 1) wal -i "$CHOICE" -o "$SCRIPT";; + 2) wal -1 "$1" --theme $2 -o $SCRIPT ;; + *) exit 0 ;; +esac + diff --git a/sort_images_by_color.py b/sort_images_by_color.py new file mode 100644 index 0000000..d5a3706 --- /dev/null +++ b/sort_images_by_color.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Sorts images in a directory by their average color and renames them +with a numeric prefix and a wallpaper-based name including the +image's average color hex code. + +Dependencies: +- Pillow: `pip install Pillow` +- tqdm (optional, for progress bar): `pip install tqdm` +""" + +import argparse +import colorsys +import sys +from pathlib import Path + +try: + from PIL import Image, UnidentifiedImageError +except ImportError: + sys.exit("Error: Pillow library not found. Please install it with 'pip install Pillow'") + +try: + from tqdm import tqdm +except ImportError: + class tqdm: + def __init__(self, iterable, *args, **kwargs): + self.iterable = iterable + def __iter__(self): + return iter(self.iterable) + def __enter__(self): + return self + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + +def get_average_color(image_path: Path) -> tuple[int, int, int] | None: + """ + Calculates the average color of an image by resizing it to a single pixel. + + Args: + image_path: The path to the image file. + + Returns: + A tuple (r, g, b) representing the average color, or None if processing fails. + """ + try: + with Image.open(image_path) as img: + img = img.convert("RGB") + avg_color_img = img.resize((1, 1), Image.Resampling.LANCZOS) + return avg_color_img.getpixel((0, 0)) + except UnidentifiedImageError: + print(f"Warning: Skipping unsupported or corrupt file: {image_path.name}") + return None + except Exception as e: + print(f"Warning: Could not process {image_path.name}: {e}") + return None + + +def main(): + parser = argparse.ArgumentParser( + description="Sort images by color and rename to 'XX_Wallpaper_.ext' format", + formatter_class=argparse.RawTextHelpFormatter + ) + parser.add_argument( + "directory", + type=str, + help="Path to directory containing images to sort." + ) + parser.add_argument( + "-n", "--dry-run", + action="store_true", + help="Perform a dry run without renaming any files." + ) + + args = parser.parse_args() + target_dir = Path(args.directory).resolve() + + if not target_dir.is_dir(): + print(f"Error: Directory not found at '{target_dir}'") + sys.exit(1) + + image_extensions = {".png", ".jpg", ".jpeg"} + image_paths = sorted([ + p for p in target_dir.iterdir() + if p.is_file() and p.suffix.lower() in image_extensions + ]) + + if not image_paths: + print(f"No images with extensions ({', '.join(image_extensions)}) found in '{target_dir}'") + sys.exit(0) + + print(f"Found {len(image_paths)} images. Analyzing colors...") + + image_data = [] + for path in tqdm(image_paths, desc="Analyzing"): + rgb = get_average_color(path) + if rgb: + hsv = colorsys.rgb_to_hsv(rgb[0]/255.0, rgb[1]/255.0, rgb[2]/255.0) + hex_code = '{:02x}{:02x}{:02x}'.format(*rgb) + image_data.append({"path": path, "hsv": hsv, "hex": hex_code}) + + sorted_images = sorted(image_data, key=lambda x: x["hsv"]) + padding = len(str(len(sorted_images))) + + print(f"\nRenaming {len(sorted_images)} images...") + if args.dry_run: + print("--- DRY RUN --- (No files will be renamed)") + + for i, data in enumerate(sorted_images, 1): + path = data["path"] + hex_code = data["hex"] + suffix = path.suffix.lower() + new_name = f"{i:0{padding}d}_Wallpaper_{hex_code}{suffix}" + new_path = path.with_name(new_name) + + if new_path.exists(): + print(f"Warning: '{new_path.name}' already exists; skipping rename of '{path.name}'.") + continue + + print(f" '{path.name}' -> '{new_path.name}'") + if not args.dry_run: + path.rename(new_path) + + print("\nDone.") + + +if __name__ == "__main__": + main() diff --git a/wallpapersync.sh b/wallpapersync.sh new file mode 100755 index 0000000..703c6c9 --- /dev/null +++ b/wallpapersync.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +Repo="/home/Nicholai/Pictures/Wallpapers" +Dir_Wallpapers="/home/Nicholai/Nextcloud/Mini-Arch/Wallpaper-Repo/" +Script_Resort="/home/Nicholai/scripts/sort_images_by_color.py" + +# 1. Resort wallpapers +python "$Script_Resort" "$Dir_Wallpapers" + +# 3. sync new wallpapers in +rsync -a --delete "$Dir_Wallpapers"/ "$Repo"/