Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (magic-webp) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
🎨 magic-webp
Fast WebP image processing in the browser using WebAssembly
Process WebP images (static and animated) directly in the browser with native performance. Built on top of Google's libwebp compiled to WebAssembly.
Features • Installation • Quick Start • API • Development
✨ Features
- 🖼️ WebP Support — Both static and animated WebP images
- ✂️ Crop — Extract regions (preserves animation frames)
- 📐 Resize — Multiple modes: cover, contain, fill, inside, outside
- 🎚️ Quality Control — Adjustable output quality (0-100, lossless)
- 🚀 Fast — Native libwebp with SIMD optimizations (5-10x faster)
- 🌐 Browser-first — No server required, runs entirely client-side
- 🔒 Thread-safe — Automatic operation queuing for concurrent calls
- 📦 Zero dependencies — Pure WebAssembly, no external libraries
📦 Installation
npm install magic-webp
# or
pnpm add magic-webp
# or
yarn add magic-webp🚀 Quick Start
import { MagicWebp } from 'magic-webp';
// Load a WebP image (static or animated)
const file = document.querySelector('input[type="file"]').files[0];
const img = await MagicWebp.fromBlob(file);
// Resize to 400x400 (cover mode - fills dimensions, crops excess)
const resized = await img.resize(400, 400, { mode: 'cover', quality: 90 });
// Get result as Blob
const blob = resized.toBlob();
// Download or display
const url = URL.createObjectURL(blob);📖 API
Loading Images
// From File/Blob
const img = await MagicWebp.fromBlob(blob);
const img = await MagicWebp.fromFile(file);
// From URL
const img = await MagicWebp.fromUrl('https://example.com/image.webp');
// From Uint8Array
const img = await MagicWebp.fromBytes(uint8Array);Transformations
All transformation methods are async and return Promise<MagicWebp>.
Crop
// Crop 200x200 region starting at (50, 50)
const cropped = await img.crop(50, 50, 200, 200, quality);Resize
// Cover - fills dimensions, crops excess (default)
const cover = await img.resize(400, 400, { mode: 'cover' });
// Contain - fits inside dimensions, preserves aspect ratio
const contain = await img.resize(400, 400, { mode: 'contain' });
// Fill - stretches to exact dimensions (may distort)
const fill = await img.resize(400, 400, { mode: 'fill' });
// Inside - like contain, but never enlarges
const inside = await img.resize(400, 400, { mode: 'inside' });
// Outside - like cover, but never reduces
const outside = await img.resize(400, 400, { mode: 'outside' });
// With position (for cover/outside modes)
const banner = await img.resize(1200, 400, {
mode: 'cover',
position: 'top', // 'center', 'top', 'bottom', 'left', 'right', etc.
quality: 90 // 0-100, default 90
});Output
// As Blob
const blob = img.toBlob();
// As Uint8Array
const bytes = img.toBytes();
// As Data URL
const dataUrl = await img.toDataUrl();
// As Object URL
const objectUrl = img.toObjectUrl();Resize Options
interface ResizeOptions {
mode?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; // default: 'cover'
position?: 'center' | 'top' | 'bottom' | 'left' | 'right' | // default: 'center'
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
quality?: number; // 0-100, default: 90
}Quality Recommendations
- 60-70: High compression, visible artifacts (good for thumbnails)
- 75-85: Balanced quality/size (recommended for most cases)
- 90-95: High quality, minimal artifacts (for important images)
- 100: Lossless, largest file size (perfect quality preservation)
Supported Formats
Input:
- ✅ Static WebP
- ✅ Animated WebP (multi-frame)
Output:
- ✅ Static WebP (from static input)
- ✅ Animated WebP (from animated input, preserves all frames and timing)
Note: All operations (crop, resize) work on both static and animated WebP. For animated images, each frame is processed individually while preserving animation metadata (timing, loop count, etc.).
💡 Examples
Static WebP - Avatar (square, centered)
const avatar = await img.resize(200, 200, { mode: 'cover', quality: 90 });Static WebP - Product Preview (fit inside container)
const preview = await img.resize(300, 300, { mode: 'contain', quality: 85 });Static WebP - Banner (crop from top)
const banner = await img.resize(1200, 400, {
mode: 'cover',
position: 'top',
quality: 90
});Animated WebP - Thumbnail (preserves all frames)
// Works with animated WebP - all frames are processed
const thumb = await img.resize(150, 150, { mode: 'inside', quality: 75 });Animated WebP - Sticker (crop and resize)
// Crop animated sticker and resize - animation is preserved
const sticker = await img
.crop(10, 10, 200, 200)
.then(cropped => cropped.resize(128, 128, { mode: 'cover' }));Chaining Operations
const result = await img
.crop(100, 100, 400, 400)
.then(cropped => cropped.resize(200, 200, { mode: 'contain' }));Concurrent Processing (thread-safe)
// All operations are automatically queued
const [avatar, thumb, banner] = await Promise.all([
img.resize(200, 200, { mode: 'cover' }),
img.resize(150, 150, { mode: 'inside' }),
img.resize(1200, 400, { mode: 'cover', position: 'top' })
]);🛠️ Development
Prerequisites
- Node.js 18+
- pnpm (recommended) or npm
- Emscripten SDK (automatically installed)
Setup
# Clone repository
git clone https://github.com/medzhidov/magic-webp.git
cd magic-webp
# Install dependencies
pnpm install
# Build WASM module
pnpm build:wasm
# Run demo
pnpm demo:watchProject Structure
magic-webp/
├── src-c/ # C source code
│ ├── animation.c # WebP animation processing
│ └── magic_webp.c # Core functions
├── src-js/ # TypeScript API
│ ├── index.ts # Main API
│ └── *.test.ts # Tests
├── demo/ # Demo application
│ ├── index.html
│ ├── main.ts
│ └── worker.ts # Web Worker for processing
├── tests/ # Native C tests
├── libwebp/ # Google's libwebp (submodule)
└── pkg/ # Built WASM outputBuild Commands
# Build WASM module
pnpm build:wasm
# Run TypeScript tests
pnpm test
# Run native C tests
pnpm test:native
# Run demo (dev server)
pnpm demo:watch
# Build demo for production
pnpm demo:buildHow It Works
- C Code (
src-c/) - Uses libwebp's WebPPicture API for high-quality image processing - Animation Support - Processes each frame individually, preserving timing and metadata
- Emscripten - Compiles C code to WebAssembly with SIMD optimizations
- TypeScript API (
src-js/) - Provides clean, type-safe interface - Operation Queue - Ensures thread-safety by serializing WASM calls
- Web Worker (demo) - Keeps UI responsive during processing
Performance
- 5-10x faster than pure JavaScript implementations
- SIMD optimizations (SSE2, NEON) for resize operations
- Optimized cover mode - single pass resize+crop (2x faster)
- Minimal memory - in-place operations where possible
📄 License
MIT © Ilia Medzhidov
🙏 Acknowledgments
- libwebp - Google's WebP library
- Emscripten - C/C++ to WebAssembly compiler
Made with ❤️ for the web