DEV Community

Aissam Irhir
Aissam Irhir

Posted on

Stop Writing Image Processing Code From Scratch — This Rust-Powered Package Does It 950x Faster

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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" }, ...]
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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!
Enter fullscreen mode Exit fullscreen mode

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
  };
}
Enter fullscreen mode Exit fullscreen mode

🤖 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));
}
Enter fullscreen mode Exit fullscreen mode

📦 Installation

# Bun (recommended)
bun add bun-image-turbo

# npm / yarn / pnpm
npm install bun-image-turbo
Enter fullscreen mode Exit fullscreen mode

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:

  1. Smart Crop — Content-aware cropping with saliency detection
  2. 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


💬 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)