kuwahara-filter 0.1.0

Fast Kuwahara filter implementation for artistic image effects
Documentation
use kuwahara_filter::args::{Args, Parser};
use kuwahara_filter::filter;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = Args::parse();

    // 1. Parse radius values
    let radii = args.parse_radius().map_err(|e| format!("Radius parsing error: {}", e))?;

    // 2. Load the image and convert to RGBA8
    let img = image::open(&args.input).map_err(|e| {
        format!("Failed to open image '{}': {}", args.input.display(), e)
    })?;
    let rgba_img = img.to_rgba8();

    // 3. Extract filename stem for output naming
    let stem = args
        .input
        .file_stem()
        .and_then(|s| s.to_str())
        .ok_or_else(|| {
            format!("Failed to extract filename from input path: {}", args.input.display())
        })?;

    // 4. Process each radius
    let radius_count = radii.len();
    
    for radius in radii.iter() {
        println!("Processing with radius {}...", radius);
        
        // Apply Kuwahara filter
        let out_img = filter::kuwahara_filter(rgba_img.clone(), *radius as i32);

        // Determine the output path
        let out_path = if let Some(ref o) = args.output {
            if radius_count == 1 {
                // Single radius: use specified output path as-is
                o.clone()
            } else {
                // Multiple radii: append radius to specified output path
                let parent = o.parent().unwrap_or_else(|| std::path::Path::new("."));
                let base_name = o.file_stem().and_then(|s| s.to_str()).unwrap_or("output");
                let extension = o.extension().and_then(|s| s.to_str()).unwrap_or("png");
                parent.join(format!("{}_r{}.{}", base_name, radius, extension))
            }
        } else {
            // Default naming scheme
            let new_name = format!("{}_kuwahara-r{}.png", stem, radius);
            if let Some(parent) = args.input.parent() {
                parent.join(new_name)
            } else {
                std::path::PathBuf::from(new_name)
            }
        };

        // Save as PNG
        out_img.save(&out_path).map_err(|e| {
            format!("Failed to save image to '{}': {}", out_path.display(), e)
        })?;
        println!("Saved Kuwahara image to {}", out_path.display());
    }

    if radius_count > 1 {
        println!("Completed processing {} images with radii {:?}", radius_count, radii);
    }

    Ok(())
}