How to Use ImageKit for Batch Image Processing: A Complete Rust CLI Guide

ImageKit processes entire directories of images in parallel using Rayon, offering batch resizing, multilingual watermarking, and format conversion through a unified CLI that orchestrates operations across src/cli.rs, src/lib.rs, and src/processor.rs without manual thread management.

ImageKit, available in the hzbd/imagekit repository, is a Rust-based command-line utility designed for high-throughput batch image processing. The tool automatically distributes workload across CPU cores while bundling required fonts for consistent watermark rendering. This guide covers how to leverage ImageKit’s architecture for efficient batch operations on large image collections.

Architecture Overview for Batch Operations

ImageKit separates concerns across four primary components to ensure reliable parallel processing:

  • CLI Definition (src/cli.rs): Parses command-line arguments using clap, handling input/output paths, resize dimensions (--width, --height), watermark options, quality settings, and output formats through a strongly-typed Cli struct.

  • Orchestration Layer (src/lib.rs): Contains the public run function that validates output directories, loads embedded fonts via src/assets.rs, collects image paths using walkdir, and drives parallel execution through Rayon’s par_iter().

  • Asset Management (src/assets.rs): Embeds TrueType/OpenType fonts (Roboto-Regular.ttf, SourceHanSansSC-Regular.otf, NotoSansThai-Regular.ttf) using rust-embed, ensuring watermark rendering remains independent of external filesystem dependencies.

  • Image Processor (src/processor.rs): Implements the per-image workflow in process_image, handling decoding, Lanczos3 resizing, multilingual text layout with rusttype, and format-aware encoding respecting quality parameters.

Basic Batch Resizing

To resize an entire directory while preserving aspect ratios, specify the target width or height. ImageKit automatically calculates the complementary dimension using the image crate’s resizing logic in src/processor.rs.

./target/release/imagekit \
    -i path/to/input_dir \
    -o path/to/output_dir \
    --width 1200

This command resizes every image to 1200px width; height scales automatically to maintain proportions.

Batch Processing with Quality Control

Control output quality for lossy formats or adjust compression levels for PNGs using the --quality flag. When set to 100 for JPEG output, ImageKit disables lossy compression entirely according to the encoder logic in src/processor.rs.

./target/release/imagekit \
    -i photos/raw \
    -o photos/resized \
    --width 1920 \
    --quality 100

Quality values map directly to encoder settings: 100 yields lossless JPEG, while 85 provides balanced compression for WebP or PNG outputs.

Adding Multilingual Watermarks to Batches

ImageKit supports mixed-script watermarks through three embedded fonts covering Latin, CJK, and Thai characters. The --watermark-position flag accepts cardinal directions (se for South-East, north for top-center, etc.) parsed in src/cli.rs.

./target/release/imagekit \
    -i assets/images \
    -o assets/watermarked \
    --watermark-text "你好, World! – 示例水印" \
    --watermark-position se \
    --font-size 32 \
    --watermark-color ffffff80

The semi-transparent white watermark (ffffff80) renders correctly across scripts because src/assets.rs bundles fonts with complementary glyph coverage.

Converting Image Formats in Bulk

Force specific output formats regardless of input type using --output-format. ImageKit handles the encoding transition in src/processor.rs, automatically adjusting pipeline parameters for PNG, WebP, or JPEG outputs.

./target/release/imagekit \
    -i collection/jpgs \
    -o collection/pngs \
    --output-format png \
    --quality 85

For PNG outputs, quality settings translate to compression levels rather than lossy quantization.

Combine resizing, watermarking, and format conversion in single invocations. The run function in src/lib.rs processes these operations sequentially per image while maintaining parallel execution across the batch.

./target/release/imagekit \
    -i src_images \
    -o processed \
    --width 1024 \
    --height 768 \
    --watermark-text "© 2026 Company" \
    --watermark-position north \
    --font-size 28 \
    --watermark-color 000000FF \
    --output-format webp \
    --quality 90

This applies fixed dimensions (1024×768), places an opaque black watermark at the top center, and converts to WebP with quality 90.

How Parallel Processing Works Under the Hood

ImageKit achieves multi-core batch processing without manual thread management through a specific pipeline in src/lib.rs:

  1. Directory Traversal: Uses walkdir::WalkDir to recursively collect all image paths from the input directory into a Vec<PathBuf>.

  2. Parallel Iteration: Feeds the collected paths to Rayon’s par_iter(), which automatically distributes images across available CPU cores.

  3. Per-Image Pipeline: Each parallel thread executes processor::process_image, performing I/O, Lanczos3 resizing, watermark rasterization, and encoding independently.

All heavy operations—including decoding, scaling, and encoding—execute in parallel, making ImageKit suitable for high-resolution photo collections where single-threaded processing would create bottlenecks.

Summary

  • ImageKit provides batch image processing through a Rust CLI that combines clap for argument parsing, walkdir for directory traversal, and Rayon for parallel execution.
  • The run function in src/lib.rs orchestrates the workflow, while src/processor.rs handles per-image resizing, multilingual watermarking, and format conversion.
  • Embedded fonts in src/assets.rs ensure reliable watermark rendering without external dependencies.
  • Commands support aspect-ratio-preserving resizes, quality-controlled encoding, and mixed-script text overlays through a unified interface.

Frequently Asked Questions

How does ImageKit handle different image formats in the same batch?

ImageKit uses the image crate’s dynamic decoding in src/processor.rs to automatically detect input formats during the image::open call. The tool processes each file according to its detected format while allowing you to standardize outputs using --output-format, enabling mixed-format input directories to convert to uniform output types in a single batch operation.

Can I use custom fonts for watermarks instead of the embedded ones?

Currently, ImageKit relies on the three fonts bundled in src/assets.rs via rust-embed (Roboto-Regular.ttf, SourceHanSansSC-Regular.otf, NotoSansThai-Regular.ttf). The processor automatically selects appropriate fonts for detected Unicode ranges. To use custom typefaces, you would need to modify src/assets.rs to embed additional font files and rebuild the binary.

What resizing filter does ImageKit use for batch operations?

According to src/processor.rs, ImageKit applies the Lanczos3 filter when resizing images. This filter provides high-quality downscaling and upscaling by sampling a larger pixel area with weighted contributions, preserving edge sharpness better than bilinear or nearest-neighbor methods during batch transformations.

How does ImageKit prevent memory exhaustion when processing thousands of images?

The tool uses Rayon’s work-stealing thread pool in src/lib.rs to limit concurrent operations to the number of logical CPU cores, preventing uncontrolled memory growth. Each par_iter() thread processes one image at a time through the complete pipeline (open → resize → watermark → save) before accepting new work, ensuring that memory usage scales with thread count rather than total batch size.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →