# How to Configure ImageKit for Recursive Image Processing

> Learn how to configure ImageKit for recursive image processing. ImageKit automatically processes all images in subdirectories by default. Get started now.

- Repository: [hzbd/imagekit](https://github.com/hzbd/imagekit)
- Tags: how-to-guide
- Published: 2026-03-03

---

**ImageKit automatically walks through every subdirectory of the supplied `input_dir` and processes all supported image files by default, requiring no special flags to enable recursion.**

ImageKit is a Rust-based batch image processing tool maintained in the `hzbd/imagekit` repository. It handles complex directory hierarchies using the `walkdir` crate to discover and process images recursively. This guide demonstrates how to configure both the CLI and Rust API to process nested image directories.

## How Recursive Traversal Works

According to the source code in `hzbd/imagekit`, recursive processing is implemented in **[`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs)** using the `walkdir` crate. The `run` function initializes a recursive iterator:

```rust
let image_paths: Vec<PathBuf> = walkdir::WalkDir::new(&cli.input_dir)

```

This iterator traverses every subdirectory beneath the specified input path. The collection logic filters entries to include only supported formats—**JPG**, **JPEG**, **PNG**, **GIF**, **BMP**, and **WEBP**—before dispatching them to **[`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs)**. Each valid path is passed to the `process_image` function, which handles resizing, watermarking, and format conversion.

Because the directory walk completes before image processing begins, **no additional configuration is required** to enable recursion. Simply provide the top-level directory to `--input-dir`.

## CLI Configuration Options

All recursive processing options are defined in **[`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs)**. These parameters apply uniformly to every image discovered during the directory traversal:

- **`-i, --input-dir <PATH>`**: Root of the recursive scan (required). Example: `--input-dir ./photos`
- **`-o, --output-dir <PATH>`**: Destination for the processed tree, preserving hierarchy (required). Example: `--output-dir ./out`
- **`--width <N>`**: Target width in pixels, with height auto-scaled. Example: `--width 1200`
- **`--height <N>`**: Target height in pixels, with width auto-scaled. Example: `--height 800`
- **`--watermark-text <STR>`**: Text overlay for each image. Example: `--watermark-text "© MyCompany"`
- **`--watermark-position <POS>`**: Watermark location using cardinal directions (`nw`, `north`, `ne`, `west`, `center`, `east`, `sw`, `south`, `se`). Example: `--watermark-position se`
- **`--font-size <N>`**: Base font size for watermarks. Example: `--font-size 36`
- **`--watermark-color <HEX>`**: RGBA hex color (default `#ffffff80`). Example: `--watermark-color "#ff0000ff"`
- **`-q, --quality <1-100>`**: JPEG/PNG output quality (default 85). Example: `--quality 90`
- **`--output-format <FMT>`**: Force specific output format (`jpg`, `png`, `webp`, etc.). Example: `--output-format png`

### Example Command

Run the following to process a nested directory structure:

```bash
cargo run --release -- \
  -i ./example/img-src \
  -o ./example/img-out \
  --width 1024 \
  --watermark-text "© MyBrand" \
  --watermark-position se \
  --font-size 48 \
  --watermark-color "#00ff00ff" \
  -q 92

```

This command recursively walks `./example/img-src`, resizes images to 1024 pixels wide, applies a green watermark in the bottom-right corner, and writes results to `./example/img-out` while maintaining the original subdirectory structure.

## Library Usage in Rust

To configure recursive processing programmatically, construct the `Cli` struct and invoke `run` from **[`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs)**:

```rust
use imagekit::{cli::Cli, run};
use std::path::PathBuf;

fn main() -> anyhow::Result<()> {
    let cli = Cli {
        input_dir: PathBuf::from("./photos"),
        output_dir: PathBuf::from("./processed"),
        width: Some(800),
        height: None,
        watermark_text: Some("© Demo".into()),
        watermark_position: imagekit::cli::WatermarkPosition::Se,
        font_size: 32,
        watermark_color: imagekit::cli::HexColor(image::Rgba([255, 255, 255, 128])),
        quality: 85,
        output_format: None,
    };

    run(cli)
}

```

The `run` function performs the identical recursive walk as the CLI, utilizing **Rayon** for parallel processing of the discovered images.

### Debugging the File Discovery

To verify which files are queued during recursion, add debug output to the iterator in **[`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs)** (around lines 45-55):

```rust
.filter_map(|e| {
    let entry = e.ok()?;
    if entry.path().is_file() && /* extension check */ {
        println!("Queued: {}", entry.path().display());
        Some(entry.path().to_path_buf())
    } else {
        None
    }
})

```

Running the binary with this modification prints every discovered image path, confirming the recursive traversal across subdirectories.

## Summary

- **Recursion is automatic**: ImageKit uses `walkdir` in [`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs) to traverse all subdirectories without extra flags.
- **Format filtering**: Only `jpg`, `jpeg`, `png`, `gif`, `bmp`, and `webp` files are processed; others are ignored.
- **Uniform processing**: All CLI options apply to every image found in the hierarchy.
- **Structure preservation**: The output directory mirrors the input directory's nested layout.
- **Dual interfaces**: Both the CLI ([`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs)) and Rust API ([`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs)) support identical recursive capabilities.

## Frequently Asked Questions

### Does ImageKit require a special flag to process subdirectories?

No. The `hzbd/imagekit` source code implements recursion by default. The `walkdir::WalkDir` iterator in [`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs) automatically descends into all subdirectories of the `--input-dir` path. No additional configuration flags are needed to enable this behavior.

### How does ImageKit handle unsupported file types during recursive scans?

The traversal logic in [`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs) filters the `walkdir` results by file extension, retaining only images matching `jpg`, `jpeg`, `png`, `gif`, `bmp`, or `webp`. Non-image files and directory entries are excluded from the `image_paths` vector before processing begins, ensuring only compatible formats reach the `process_image` function in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs).

### Will the output directory maintain the same folder structure as the input?

Yes. ImageKit preserves the relative path hierarchy from the input root to the output root. A file located at `./photos/2024/vacation/image.jpg` appears in the output directory at `./processed/2024/vacation/image.jpg`, maintaining your organizational structure throughout the recursive batch operation.

### Can I limit the recursion depth or exclude specific subdirectories?

The current implementation in [`src/lib.rs`](https://github.com/hzbd/imagekit/blob/main/src/lib.rs) uses the default `walkdir` configuration without depth limits or exclude patterns. To restrict processing, you must either reorganize your source directory structure or manually filter the `image_paths` vector before it enters the parallel processing stage within the `run` function.