npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@sorabito-takano/wasm-image-optimization

v1.2.2

Published

WebP image optimization with Lanczos resampling on edge runtime

Downloads

30

Readme

wasm-image-optimization

WebAssembly-based image optimization library with a custom minimal resize core (OpenCV runtime removed for smaller wasm size) using extracted high-quality Lanczos resampling logic from pillow-resize. Primary target is WebP (auto lossless for PNG/WebP inputs, lossy otherwise) with optional JPEG output and a pass-through ("none") mode that returns the original bytes (useful when only resizing info or EXIF-based orientation handling is needed).

  • Frontend

    • Next.js (Multithreading support)
    • React Router (Multithreading support)
  • Backend

    • Cloudflare Workers
    • Deno Deploy
    • Node.js (Multithreading support)

Supported Conversions

  • Input formats (auto-detected): JPEG / PNG / WebP
  • Output formats:
    • webp – High-quality Lanczos resize using pillow-resize implementation, auto lossless for PNG/WebP sources, lossy otherwise
    • jpeg – Always lossy JPEG (RGB → YCbCr), ignores lossless flag
    • none – Returns original bytes untouched (width/height/EXIF orientation still processed)

Example

https://next-image-convert.vercel.app/

API

Core Functions

Image conversion (all functions return Promises):

optimizeImage({
  image: ArrayBuffer | Uint8Array | string,
  width?: number,
  height?: number,
  quality?: number,   // 0-100 (default 100)
  format?: "webp" | "jpeg" | "none" // default: webp
}): Promise<Uint8Array>

optimizeImageExt({
  image: ArrayBuffer | Uint8Array | string,
  width?: number,
  height?: number,
  quality?: number,
  format?: "webp" | "jpeg" | "none"
}): Promise<{
  data: Uint8Array,
  originalWidth: number,
  originalHeight: number,
  width: number,
  height: number
}>

Multi-thread / Worker Control

waitAll(): Promise<void>
waitReady(retryTime?: number): Promise<void>
close(): void
launchWorker(): Promise<void>
setLimit(maxWorkers: number): void   // (exported but previously undocumented)

WASM Path Configuration (PWA / Offline Support)

For PWA applications or custom deployment scenarios, you can configure the WebAssembly binary location:

import { setWasmUrl, setWasmBinary } from 'wasm-image-optimization/vite';

// Option 1: Set custom WASM URL (useful for PWA Service Worker caching)
setWasmUrl('/assets/libImage.wasm');

// Option 2: Provide pre-loaded WASM binary
const wasmBinary = await fetch('/assets/libImage.wasm').then(r => r.arrayBuffer());
setWasmBinary(wasmBinary);

// Reset to default behavior
import { resetWasmConfig } from 'wasm-image-optimization/vite';
resetWasmConfig();

Available in: vite, next, workers, node entry points.

Vite / Web Worker Integration

For Vite usage include the plugin (adds proper asset copying and worker wiring):

  • vite.config.ts
import wasmImageOptimizationPlugin from "wasm-image-optimization/vite-plugin";

export default defineConfig(() => ({
  plugins: [
    wasmImageOptimizationPlugin(),
    //wasmImageOptimizationPlugin("build/client/assets") // optional: assetsPath
  ],
}));

Build

Architecture-aware Docker Build

Automatic host architecture detection (x86_64 / arm64) is handled by the helper script:

# Automatic architecture detection and build
pnpm build:wasm:auto

# Or use the architecture detection script directly
./scripts/docker-build.sh all

# Manual architecture selection (override detection)
pnpm docker:arm64    # Force ARM64 build
pnpm docker:x86      # Force x86_64 build

Incremental Development (Docker)

# Build environment setup
pnpm docker:build-env

# Start development environment
pnpm docker:dev

# Run make in Docker
pnpm docker:make

# Open shell in Docker
pnpm docker:shell-dev

# Clean up Docker resources  
pnpm docker:stop

Direct One-shot Build (manual override)

# For ARM64 (Apple Silicon)
DOCKERFILE=./docker/Dockerfile.arm64 docker compose -f docker/docker-compose.auto.yml run --rm dev make all

# For x86_64
DOCKERFILE=./docker/Dockerfile docker compose -f docker/docker-compose.auto.yml run --rm dev make all

Supported Environments & Entry Points

| Environment / Use Case | Import Path | |---------------------------------------|----------------------------------------------------| | Cloudflare Workers / Edge (ESM) | wasm-image-optimization | | Next.js (SSR + Web Worker mode) | wasm-image-optimization/next | | Next.js API Route (explicit) | wasm-image-optimization/next-api | | Generic ESM / Deno Deploy | wasm-image-optimization | | Node.js (single thread) | wasm-image-optimization | | Node.js (multi thread pool) | wasm-image-optimization/node-worker | | Vite (bundled browser main thread) | wasm-image-optimization/vite | | Vite / Generic Web Worker (multi) | wasm-image-optimization/web-worker | | Raw Worker (CJS fallback) | wasm-image-optimization/node |

Multi-thread variants expose waitReady, waitAll, launchWorker, setLimit, close.

Samples

Repository with usage examples: https://github.com/SoraKumo001/wasm-image-optimization-samples

Behavior Notes

  • EXIF orientation is automatically normalized before resizing/encoding.
  • WebP encoding switches to lossless when input is PNG or WebP and output format is webp.
  • format: "none" returns the original bytes (useful when you only need metadata or want to defer encoding).
  • quality only affects lossy paths (WebP lossy / JPEG). Lossless WebP ignores the numeric quality parameter.

Image Processing Details

This library integrates high-quality image resampling algorithms extracted from pillow-resize for superior image quality compared to typical naive or bilinear scaling approaches. OpenCV is no longer shipped to drastically reduce WASM size.

Minimal Resize Core & Lanczos Resampling

| Aspect | Before (OpenCV based) | Now (Custom minimal core) | |--------|-----------------------|---------------------------| | WASM size (typical) | ~1.5 MB | ~ (significantly smaller)* | | Dependency | OpenCV (core/imgproc subset) | Hand-extracted resize pipeline | | Filter | OpenCV Lanczos / fallback logic | Direct Lanczos-3 implementation | | Fallback path | OpenCV INTER_LANCZOS4 | Removed (deterministic path) |

*Exact size depends on build flags; OpenCV code paths, alloc helpers, and unused kernels removed.

Key Points

  • Only the math & buffer ops needed for Lanczos-3 down/upsampling are compiled.
  • No dynamic dispatch / no unused interpolation kernels.
  • Deterministic single path (no runtime fallback → smaller + predictable output).
  • Implements horizontal + vertical separable filtering with windowed sinc (Lanczos radius=3).
  • Designed for future extension (e.g. optional Mitchell / Catmull-Rom) without pulling large frameworks.

Why remove OpenCV?

  • Large binary footprint (initial builds ~1.5MB → unacceptable for some edge/PWA budgets)
  • Only resize + color conversion were used.
  • Custom path eliminates build complexity (Python + CMake toolchain for OpenCV JS).
  • Faster cold start under Service Worker / edge runtime due to reduced instantiation cost.

Quality

Lanczos-3 maintains sharpness while minimizing ringing for photographic sources. For heavy downscales (<25%) you may still apply an external pre-blur if aggressive aliasing in source exists.

If you previously relied on OpenCV-specific behavior (e.g. other interpolation modes), migrate by calling optimizeImage with the same resize parameters — behavior is now unified.

Roadmap / TODO

  • Expose pluggable resize kernels (Mitchell, Catmull-Rom, Lanczos-2).
  • Optional AVIF output (investigation phase).
  • Update published TypeScript types to include "jpeg" (if not already updated in release at read time).
  • Optional prefilter for extreme downscale scenarios.

MIT License