iwaku config changes, load changes, hypr support only IF passed the same as zshell

This commit is contained in:
2026-05-13 13:59:42 +02:00
parent 075cd42064
commit cf634a76f2
5 changed files with 70 additions and 74 deletions
-7
View File
@@ -9,10 +9,3 @@ target/
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# RustRover
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
Generated
+11 -11
View File
@@ -405,6 +405,17 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "iwaku"
version = "0.1.0"
dependencies = [
"anyhow",
"image",
"serde",
"serde_json",
"tiny-skia",
]
[[package]]
name = "jobserver"
version = "0.1.34"
@@ -790,17 +801,6 @@ version = "0.8.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
[[package]]
name = "rs-pictures"
version = "0.1.0"
dependencies = [
"anyhow",
"image",
"serde",
"serde_json",
"tiny-skia",
]
[[package]]
name = "rustversion"
version = "1.0.22"
+7 -19
View File
@@ -1,39 +1,27 @@
[package]
name = "rs-pictures"
name = "iwaku"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "rs-pictures"
name = "iwaku"
path = "src/main.rs"
[dependencies]
# Image loading and encoding
image = { version = "0.25", features = ["png", "jpeg"] }
# 2D rendering for effects (rounded corners, drop shadow)
image = { version = "0.25", features = ["png"] }
tiny-skia = "0.11"
# Config serialization
serde = { version = "1", features = ["derive"] }
# Error handling
anyhow = "1"
serde_json = "1.0.149"
# ── Build profiles ────────────────────────────────────────────────────────────
[profile.release]
opt-level = 3
lto = "thin" # link-time optimisation across crates
codegen-units = 1 # better inlining at the cost of compile time
strip = true # strip debug symbols → smaller binary
lto = "thin"
codegen-units = 1
strip = true
# Dev builds are slow for pixel-processing code. This gives opt-level 2
# to our own crate only while keeping dependencies at their default (opt=3
# they already compiled with), so incremental rebuilds stay fast.
[profile.dev]
opt-level = 0
[profile.dev.package."*"]
opt-level = 3 # all deps at full optimisation even in dev mode
opt-level = 3
+6 -25
View File
@@ -5,11 +5,12 @@ use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
#[serde(rename = "screenshot")]
pub effects: EffectsConfig,
pub screenshot: EffectsConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EffectsConfig {
pub mode: String,
pub rounded_corners: bool,
pub corner_radius: f32,
pub drop_shadow: bool,
@@ -19,28 +20,6 @@ pub struct EffectsConfig {
pub shadow_color: [u8; 4],
}
impl Default for EffectsConfig {
fn default() -> Self {
Self {
rounded_corners: false,
corner_radius: 12.0,
drop_shadow: false,
shadow_blur_radius: 20.0,
shadow_offset_x: 5.0,
shadow_offset_y: 8.0,
shadow_color: [0, 0, 0, 160],
}
}
}
impl Default for Config {
fn default() -> Self {
Self {
effects: EffectsConfig::default(),
}
}
}
impl Config {
pub fn config_path() -> Option<PathBuf> {
let home = std::env::var("HOME").ok()?;
@@ -54,10 +33,12 @@ impl Config {
pub fn load() -> Result<Self> {
let path = Self::config_path().context("Could not determine HOME directory")?;
Self::load_from(&path)
}
let raw = std::fs::read_to_string(&path)
pub fn load_from(path: &PathBuf) -> Result<Self> {
let raw = std::fs::read_to_string(path)
.with_context(|| format!("Failed to read config at {}", path.display()))?;
serde_json::from_str(&raw)
.with_context(|| format!("Failed to parse JSON config at {}", path.display()))
}
+46 -12
View File
@@ -1,36 +1,70 @@
mod config;
mod effects;
use anyhow::{Context, Result};
use anyhow::{bail, Context, Result};
use std::io::Write as _;
use std::path::PathBuf;
use std::process::{Command, Stdio};
fn main() -> Result<()> {
let paths: Vec<String> = std::env::args().skip(1).collect();
let args: Vec<String> = std::env::args().skip(1).collect();
if paths.is_empty() {
eprintln!("Usage: rs-pictures <image> [image2 ...]");
eprintln!("No image paths provided.");
std::process::exit(1);
let mut image_path: Option<String> = None;
let mut hypr_path: Option<String> = None;
let mut i = 0;
while i < args.len() {
match args[i].as_str() {
"-image" => {
i += 1;
image_path = Some(
args.get(i)
.cloned()
.context("Expected a path after -image")?,
);
}
"-hypr" => {
i += 1;
hypr_path = Some(
args.get(i)
.cloned()
.context("Expected a path after -hypr")?,
);
}
unknown => bail!("Unknown argument: {unknown}"),
}
i += 1;
}
let image_path =
image_path.context("Usage: iwaku -image <path> [-hypr <config_path>]\nMissing -image")?;
let config = config::Config::load().context("Failed to load config")?;
for path in &paths {
if let Err(e) = process_image(path, &config) {
eprintln!("Error processing '{}': {e:#}", path);
}
let effects = if config.screenshot.mode == "auto" {
let hypr_config_path = hypr_path
.map(PathBuf::from)
.context("Mode is 'auto' but -hypr <config_path> was not provided")?;
let hypr_config =
config::Config::load_from(&hypr_config_path).context("Failed to load hypr config")?;
hypr_config.screenshot
} else {
config.screenshot
};
if let Err(e) = process_image(&image_path, &effects) {
eprintln!("Error processing '{}': {e:#}", image_path);
}
Ok(())
}
fn process_image(path: &str, config: &config::Config) -> Result<()> {
fn process_image(path: &str, effects: &config::EffectsConfig) -> Result<()> {
let img = image::open(path)
.with_context(|| format!("Failed to open image '{path}'"))?
.into_rgba8();
let processed = effects::apply_effects(img, &config.effects);
let processed = effects::apply_effects(img, effects);
let mut png_bytes: Vec<u8> = Vec::new();
image::DynamicImage::ImageRgba8(processed)