What if I told you that the image processing code you've been writing for hours could be reduced to a single line — and run 950x faster?
I've been building image-heavy applications for years. Profile picture uploads, thumbnail generation, ML preprocessing, duplicate detection... the same problems, over and over. Sharp was okay, but I kept hitting walls:
- 🐌 Slow metadata extraction
- 😤 No native smart cropping
- 🤯 Manual tensor conversion for ML pipelines
- 💀 Memory explosions on large images
So I built something better. bun-image-turbo — a Rust-powered image processing library that's genuinely changing how I build.
🎯 Who Is This For?
Web Developers
- Building apps with user-uploaded images
- Need thumbnails, avatars, social media crops
- Want image placeholders that don't suck
AI/ML Engineers
- Preprocessing images for models (ResNet, CLIP, YOLO)
- Need fast tensor conversion without Python
- Building image similarity/duplicate detection
Full-Stack Engineers
- E-commerce product images
- Content management systems
- Any app where images = core feature
🚀 The Features That Actually Matter
1. Smart Crop — No More Manual Coordinates
import { smartCrop } from 'bun-image-turbo';
// Old way: manually calculate crop coordinates 😩
// New way: one line, AI finds the best region 🎯
const thumbnail = await smartCrop(buffer, { aspectRatio: '1:1' });
// Perfect square crop, focused on the interesting part
Smart crop uses saliency detection to find faces, objects, and visually interesting areas. Works for any aspect ratio:
const instagram = await smartCrop(buffer, { aspectRatio: '1:1' }); // Square
const youtube = await smartCrop(buffer, { aspectRatio: '16:9' }); // Landscape
const tiktok = await smartCrop(buffer, { aspectRatio: '9:16' }); // Portrait
Use case: Profile pictures, social media thumbnails, e-commerce product images — anything where you need intelligent cropping without user intervention.
2. Dominant Colors — Spotify-Style UI Theming
import { dominantColors } from 'bun-image-turbo';
const { primary, colors } = await dominantColors(albumArt);
// Auto-theme your UI
document.body.style.backgroundColor = primary.hex;
console.log(colors);
// [{ r: 52, g: 152, b: 219, hex: "#3498DB" }, ...]
Use cases:
- 🎵 Music apps (theme based on album art)
- 🛒 E-commerce (match card backgrounds to products)
- 🖼️ Galleries (color-coordinated layouts)
- ⏳ Loading states (colored placeholder while image loads)
3. ML Tensor Conversion — First Native SIMD Implementation in JavaScript
This is the one that made me build this library. Every ML project needs image → tensor conversion. Python has it easy. JavaScript? Not so much.
Until now.
import { toTensor } from 'bun-image-turbo';
const tensor = await toTensor(buffer, {
width: 224,
height: 224,
normalization: 'Imagenet', // Built-in presets!
layout: 'Chw', // PyTorch/ONNX format
batch: true // Add batch dimension
});
// Shape: [1, 3, 224, 224] — Ready for inference!
console.log(tensor.shape);
Built-in normalization presets:
-
Imagenet— ResNet, VGG, EfficientNet -
Clip— CLIP, OpenCLIP, BLIP models -
ZeroOne— Scale to [0, 1] -
NegOneOne— Scale to [-1, 1]
Performance: 10-16x faster than JavaScript alternatives. SIMD-accelerated, parallel channel processing.
4. Perceptual Hashing — Find Duplicate/Similar Images
import { imageHash, imageHashDistance } from 'bun-image-turbo';
const hash1 = await imageHash(image1, { algorithm: 'PHash' });
const hash2 = await imageHash(image2, { algorithm: 'PHash' });
const distance = imageHashDistance(hash1.hash, hash2.hash);
if (distance < 5) console.log('Nearly identical!');
else if (distance < 10) console.log('Similar');
else console.log('Different');
Unlike MD5/SHA hashes, perceptual hashes let similar images have similar hashes. Resized? Compressed? Slightly cropped? Still matches.
Use cases:
- 🔍 Duplicate detection in uploads
- 🚫 Content moderation
- 🔄 Reverse image search
- ©️ Copyright detection
5. ThumbHash Placeholders — Better Than BlurHash
import { thumbhash } from 'bun-image-turbo';
const { dataUrl } = await thumbhash(buffer);
// Use directly in HTML/CSS
<img src={dataUrl} /> // Instant placeholder!
Why ThumbHash > BlurHash:
- ✅ Alpha channel support
- ✅ Preserves aspect ratio
- ✅ Better color accuracy
- ✅ Smoother gradients
⚡ Performance That Actually Matters
| Operation | bun-image-turbo | Alternative | Speedup |
|---|---|---|---|
| Metadata extraction | 0.05ms | 47.5ms (sharp) | 950x |
| JPEG resize | 12ms | 15ms | 1.25x |
| Tensor conversion | 12.5ms | 200ms+ | 16x |
| Perceptual hash | 8ms | 150ms+ | 18x |
Why so fast?
- 🦀 Pure Rust core
- ⚡ SIMD acceleration (SSE2/AVX2/NEON)
- 🔄 Zero-copy operations where possible
- 📦 Shrink-on-load (decode at target size)
🛠️ Real-World Example: Social Media Image Pipeline
import {
smartCrop,
dominantColors,
thumbhash,
resize,
toWebp
} from 'bun-image-turbo';
async function processUpload(buffer: Buffer) {
// 1. Generate placeholder instantly
const placeholder = await thumbhash(buffer);
// 2. Get theme colors
const { primary } = await dominantColors(buffer, 1);
// 3. Generate all social crops in parallel
const [instagram, youtube, twitter] = await Promise.all([
smartCrop(buffer, { aspectRatio: '1:1' }),
smartCrop(buffer, { aspectRatio: '16:9' }),
smartCrop(buffer, { aspectRatio: '16:9' }),
]);
// 4. Resize and optimize
const thumbnails = await Promise.all([
toWebp(await resize(instagram, { width: 1080 }), { quality: 85 }),
toWebp(await resize(youtube, { width: 1280 }), { quality: 85 }),
toWebp(await resize(twitter, { width: 1200 }), { quality: 85 }),
]);
return {
placeholder: placeholder.dataUrl,
themeColor: primary.hex,
thumbnails
};
}
🤖 AI/ML Example: Image Classification Pipeline
import { toTensor, metadata } from 'bun-image-turbo';
async function preprocessForModel(imageBuffer: Buffer) {
// Check image info
const info = await metadata(imageBuffer);
console.log(`Processing ${info.width}x${info.height} ${info.format}`);
// Convert to tensor with ImageNet normalization
const tensor = await toTensor(imageBuffer, {
width: 224,
height: 224,
normalization: 'Imagenet',
layout: 'Chw',
batch: true
});
// Ready for ONNX Runtime, TensorFlow.js, etc.
return tensor.toFloat32Array();
}
// Batch processing
async function processBatch(images: Buffer[]) {
return Promise.all(images.map(preprocessForModel));
}
📦 Installation
# Bun (recommended)
bun add bun-image-turbo
# npm / yarn / pnpm
npm install bun-image-turbo
Works with Bun and Node.js. Native binaries for:
- macOS (ARM64 + x64)
- Linux (x64 + ARM64)
- Windows (x64 + ARM64)
🎁 What's New in v1.9.0
Just released:
- Smart Crop — Content-aware cropping with saliency detection
- Dominant Colors — Extract color palettes for UI theming
Previous releases added:
- v1.8.0: Perceptual Hashing (pHash, dHash, aHash)
- v1.7.0: ML Tensor Conversion with SIMD
- v1.6.0: Zero-copy Cropping API
- v1.5.0: ThumbHash support
🔗 Links
- GitHub: github.com/nexus-aissam/bun-image-turbo
- npm: npmjs.com/package/bun-image-turbo
- Docs: nexus-aissam.github.io/bun-image-turbo
💬 Final Thoughts
I built this because I was tired of:
- Slow image processing blocking my app
- Writing the same thumbnail/crop/resize code
- Manual ML preprocessing in JavaScript
- Choosing between performance and features
bun-image-turbo gives you both. Native Rust speed with a clean TypeScript API.
Try it. Break it. Open issues. Let's make image processing in JavaScript not suck anymore.
What image processing pain points do you deal with? Drop a comment below! 👇
Top comments (0)