# How ImageKit Smart Scaling Works for Image Resizing in Rust

> Discover how ImageKit smart scaling in Rust preserves aspect ratios and resizes images with high-quality Lanczos3 resampling. Learn how it works in our processor.

- Repository: [hzbd/imagekit](https://github.com/hzbd/imagekit)
- Tags: deep-dive
- Published: 2026-03-03

---

**ImageKit's smart scaling automatically preserves aspect ratios when only one dimension is specified, calculates proportional dimensions using floating-point ratios, and applies Lanczos3 resampling for high-quality output, all within the `process_image` function in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs).**

The `hzbd/imagekit` repository provides a Rust-based CLI and library for batch image processing. Its smart scaling algorithm eliminates manual calculation when resizing images, ensuring that single-dimension constraints maintain original proportions while still supporting explicit width-height pairs for forced transformations.

## How the Smart Scaling Algorithm Works

The core logic resides in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs) inside the `process_image` function. When you provide `--width` or `--height` arguments via the CLI, the algorithm determines whether to preserve the aspect ratio or force specific dimensions.

### Detecting Resize Requirements

The algorithm first checks if resizing is requested by examining the CLI options. A boolean flag `needs_resize` tracks whether processing is necessary.

```rust
let mut needs_resize = false;
let (new_width, new_height) = match (cli.width, cli.height) {
    (Some(w), None) => { /* single dimension logic */ },
    (None, Some(h)) => { /* single dimension logic */ },
    (Some(w), Some(h)) => { needs_resize = true; (w, h) },
    (None, None) => (original_width, original_height),
};

```

This pattern match (lines 17-37 in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs)) handles four distinct scenarios: width-only, height-only, both dimensions, or no scaling.

### Single-Dimension Aspect Ratio Preservation

When you specify only one dimension, ImageKit calculates the other automatically to prevent distortion. The algorithm converts integers to `f32` for precise division, then rounds the result.

**Width-only scaling** (`--width 800`):

```rust
(Some(w), None) => {
    needs_resize = true;
    let ratio = original_height as f32 / original_width as f32;
    let h = (w as f32 * ratio).round() as u32;
    (w, h.max(1))
}

```

**Height-only scaling** (`--height 600`):

```rust
(None, Some(h)) => {
    needs_resize = true;
    let ratio = original_width as f32 / original_height as f32;
    let w = (h as f32 * ratio).round() as u32;
    (w.max(1), h)
}

```

Both branches include a `max(1)` safety guard to ensure dimensions never round to zero, preventing invalid image states (source: [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs) lines 20-34).

### Explicit Dimension Overrides

When you supply both `--width` and `--height`, smart scaling defers to your explicit instructions, potentially altering the aspect ratio:

```rust
(Some(w), Some(h)) => { needs_resize = true; (w, h) },

```

This behavior (line 36) allows for intentional stretching or squaring of images when required.

### High-Quality Resampling with Lanczos3

After calculating target dimensions, the actual resize operation uses the `image` crate's `resize_exact` method with the **Lanczos3** filter. This filter provides superior quality for downscaling by sampling across a larger pixel window.

```rust
if needs_resize && (new_width != original_width || new_height != original_height) {
    img = img.resize_exact(new_width, new_height, image::imageops::FilterType::Lanczos3);
}

```

The conditional check (lines 40-42) ensures that if the target dimensions match the original, no CPU-intensive resampling occurs.

## Using Smart Scaling from the Command Line

The CLI in `hzbd/imagekit` exposes smart scaling through intuitive flags that map directly to the algorithm described above.

**Preserve aspect ratio with width constraint:**

```bash
imagekit -i ./photos -o ./out --width 800

```

**Preserve aspect ratio with height constraint:**

```bash
imagekit -i ./photos -o ./out --height 600

```

**Force specific dimensions (aspect ratio may change):**

```bash
imagekit -i ./photos -o ./out --width 400 --height 300

```

Each command invokes `process_image` in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs), where the smart scaling logic evaluates your inputs and applies the appropriate calculation method.

## Implementing Smart Scaling in Rust Code

You can leverage the same algorithm programmatically by importing the processor module and constructing a `Cli` configuration object.

**Basic programmatic resize:**

```rust
use imagekit::processor::process_image;
use imagekit::cli::Cli;
use rusttype::Font;
use std::path::Path;

// Configure for width-only smart scaling
let cli = Cli {
    input_dir: Path::new("./photos").to_path_buf(),
    output_dir: Path::new("./out").to_path_buf(),
    width: Some(800),
    height: None,
    ..Default::default()
};

let fonts: Vec<Font<'static>> = vec![];
process_image(&Path::new("./photos/pic.jpg"), &cli, &fonts)
    .expect("Failed to resize image");

```

**Batch processing with smart scaling:**

```rust
use imagekit::processor::process_image;
use imagekit::cli::Cli;
use rusttype::Font;
use std::fs;
use std::path::Path;

fn batch_smart_resize(input_dir: &Path, output_dir: &Path, target_width: u32) -> anyhow::Result<()> {
    let cli = Cli {
        input_dir: input_dir.to_path_buf(),
        output_dir: output_dir.to_path_buf(),
        width: Some(target_width),
        height: None,
        ..Default::default()
    };
    let fonts = vec![];

    for entry in fs::read_dir(input_dir)? {
        let entry = entry?;
        if entry.path().is_file() {
            process_image(&entry.path(), &cli, &fonts)?;
        }
    }
    Ok(())
}

```

In both examples, setting only `width` triggers the aspect-ratio-preserving branch of the smart scaling algorithm, automatically calculating unique heights for each image based on its original dimensions.

## Summary

- **Smart scaling** in `hzbd/imagekit` automatically calculates missing dimensions to preserve aspect ratios when only width or height is specified.
- The algorithm uses **floating-point ratios** with rounding and `max(1)` guards to prevent zero-dimensional outputs.
- **Explicit width-height pairs** bypass aspect ratio preservation, allowing forced resizes.
- All resizing uses the **Lanczos3** filter via the `image` crate for high-quality output.
- The logic is contained in [`src/processor.rs`](https://github.com/hzbd/imagekit/blob/main/src/processor.rs) within the `process_image` function, triggered by CLI options defined in [`src/cli.rs`](https://github.com/hzbd/imagekit/blob/main/src/cli.rs).

## Frequently Asked Questions

### What is smart scaling in ImageKit?

Smart scaling is ImageKit's algorithm for intelligent dimension calculation during image resizing. When you provide only a width or only a height, the system automatically computes the complementary dimension using the original aspect ratio, preventing distortion without requiring manual mathematical input from the user.

### How does ImageKit preserve aspect ratios?

ImageKit preserves aspect ratios by calculating proportional dimensions using floating-point division. For width-only requests, it computes `height = (width × original_height) / original_width`. For height-only requests, it computes `width = (height × original_width) / original_height`. Both calculations round to the nearest integer and enforce a minimum value of 1 pixel.

### What resampling filter does ImageKit use for resizing?

ImageKit uses the **Lanczos3** filter from the `image` crate, specified as `image::imageops::FilterType::Lanczos3`. This filter provides high-quality results by considering a larger window of source pixels during the resampling process, particularly effective for downscaling operations.

### Can I disable smart scaling and force exact dimensions?

Yes. Smart scaling only activates when a single dimension is provided. If you specify both `--width` and `--height` via the CLI, or set both `Some(w)` and `Some(h)` in the `Cli` struct programmatically, ImageKit resizes to those exact dimensions, potentially altering the aspect ratio according to your requirements.