Reduce Image Size (Resize)
About the resize feature
What is it? Resize changes the height and width of JPG or PNG images before delivery. Set dimensions and fit mode using query parameters.
Example: Origin hosts 1100×1500 px image. With width=800&height=600, users receive 800×600 version. Origin unchanged.
Enable resize
Resize is included in the Image Optimizer service. Add query parameters to image URLs.
Use resize
Add query strings to image URLs:
image.jpg?width=800
image.jpg?height=600
image.jpg?width=800&height=600&fit=bounds
Resize parameters
Width
Resizes to specific width, preserving aspect ratio. Height calculated automatically.
?width=800
Height
Resizes to specific height, preserving aspect ratio. Width calculated automatically.
?height=600
Fit modes
Controls resize behavior when both width and height specified.
| Mode | Behavior | Use Case |
|---|---|---|
| fit | Resize + center crop to exact dimensions | Thumbnails, cards |
| bounds | Use greater dimension, resize proportionally | Flexible layouts |
| cover | Use smaller dimension, resize proportionally | Hero images |
| force | Force exact size, may distort | Exact dimensions needed |
Default: fit=fit
fit=fit (default)
Resizes to cover the target area, then crops from center to exact dimensions.
Example: Origin image is 1000×500. You specify width=800&height=600.
- Scale ratio: max(800/1000, 600/500) = 1.2
- Resize to 1200×600, then crop center to 800×600.
?width=800&height=600&fit=fit
fit=bounds
Uses the greater of the two specified dimensions and resizes proportionally. The smaller dimension value is ignored; the other dimension is calculated from the aspect ratio.
Example: Origin image is 1000×500. You specify width=500&height=300.
- Width (500) is greater than height (300), so width is used.
- Aspect ratio is 2:1, so height = 500 / 2 = 250.
- Result: 500×250.
?width=500&height=300&fit=bounds
fit=cover
Uses the smaller of the two specified dimensions and resizes proportionally. The larger dimension value is ignored; the other dimension is calculated from the aspect ratio.
Example: Origin image is 1000×500. You specify width=500&height=300.
- Height (300) is smaller than width (500), so height is used.
- Aspect ratio is 2:1, so width = 300 × 2 = 600.
- Result: 600×300.
?width=500&height=300&fit=cover
fit=force
Forces exact dimensions, ignoring aspect ratio. May distort the image. Use sparingly.
?width=800&height=600&fit=force
Usage examples
<!-- Single dimension -->
<img src="photo.jpg?width=800" alt="Photo" />
<img src="photo.jpg?height=600" alt="Photo" />
<!-- Both dimensions -->
<img src="photo.jpg?width=800&height=600" alt="Photo" />
<!-- With fit mode -->
<img src="photo.jpg?width=800&height=600&fit=bounds" alt="Photo" />
<!-- Resize + quality -->
<img src="photo.jpg?width=800&quality=80" alt="Photo" />
<!-- Resize + crop + WebP -->
<img src="photo.jpg?width=1200&crop=16:9&fmt=webp" alt="Photo" />
Responsive images
<picture>
<source srcset="image.jpg?width=1200" media="(min-width: 1200px)" />
<source srcset="image.jpg?width=800" media="(min-width: 800px)" />
<img src="image.jpg?width=400" alt="Responsive" />
</picture>
Check HTTP headers
curl -I https://your-cdn.com/image.jpg?width=800&height=600
Expected: X-Img-Operations: resizing
Limitations
Upscaling not supported
- Requests larger than the original are rejected
- Resize is skipped and other operations continue
- Solution: Use appropriate source resolution
Dimension limits
- Range: 1-10,000 px per side
- Out of range values ignored
- Large source images may hit the 150 MB resize memory budget (see Memory and dimension limits)
See limitations.md for details.
Processing order
- Resize - First
- Crop - Second
- Format + Quality - Last
Memory and dimension limits
The resize operation runs inside a Wasm module with limited memory (~150-200 MB).
How resize memory is calculated
The resizer uses a two-pass algorithm (horizontal then vertical) with u8 intermediates:
peak memory = source + intermediate + destination
= (src_w × src_h × C) + (target_w × src_h × C) + (target_w × target_h × C)
Where C = 3 for RGB sources (JPEG, opaque PNG) or C = 4 for RGBA sources (PNG with transparency).
Maximum target dimensions (150 MB budget)
| Source dimensions | Source type | Max target (approx) | Peak memory |
|---|---|---|---|
| 4096×4096 | RGB (C=3) | ~4050×4050 | 142 MB |
| 5499×2700 | RGB (C=3) | ~4800×2360 | 148 MB |
| 6000×4000 | RGB (C=3) | ~3800×2533 | 147 MB |
| 4096×4096 | RGBA (C=4) | ~2900×2900 | 148 MB |
| 5499×2700 | RGBA (C=4) | ~3500×1718 | 147 MB |
Calculating the max target width for your image
For a width-only resize (aspect ratio preserved):
target_h = src_h × target_w / src_w
max_target_w = (budget - src_w × src_h × C) / (src_h × C + target_h × C)
Where budget = 150 × 1024 × 1024 bytes (157,286,400).
What happens when the limit is exceeded
A pre-flight check estimates memory before allocating. If the estimate exceeds the budget:
- The resize is skipped (not attempted)
- The original full-resolution image is served
- A log entry is written:
Resize would require ~X MB, exceeding 150 MB budget - Other operations (crop, quality, format conversion) still apply
Performance
| Operation | Time | Status |
|---|---|---|
| Resize | <100ms | ✅ Excellent |
| Resize + Crop | <150ms | ✅ Excellent |
Uses CatmullRom (bicubic) filter via fast_image_resize crate for high-quality, memory-efficient resampling.
Troubleshooting
Resize not applied: Check syntax ?width=800, verify dimension limits (1-10000)
Upscaling warning: Don't request larger than original dimensions
Unexpected aspect ratio: Choose correct fit mode (bounds/cover/fit/force)