Skip to content

Changelog ​

All notable changes to imgkit.

[2.4.0] - 2026-09-14 ​

Added ​

  • WebAssembly build - imgkit now runs on platforms with no prebuilt native addon (Issue #12)

    • Compiled from the same Rust source as the native addon for wasm32-wasip1-threads via napi-rs/emnapi
    • bun run build:wasm emits to wasm/; the module and both loaders ship in the package
    • src/loader.ts falls back to WebAssembly after every native strategy, so an unsupported platform degrades instead of throwing at import. Verified by installing the packed tarball into a clean project.
    • New codecBackend() reports the loaded backend and its capabilities at runtime
    • Browser and edge support is not finished. The artifacts ship, but the browser entry point is still to be built, so import 'imgkit' does not yet work in a bundle. napi's generated browser.js re-exports an unpublished package and would bypass the TypeScript layer, so no browser export condition is advertised.
    • See the WebAssembly guide for the full trade-off table
  • native-codecs cargo feature - the C codecs (libjpeg-turbo, libwebp) are now optional

    • --no-default-features builds with pure-Rust codecs and zero C dependencies, so the crate builds without nasm/cmake
    • This is what makes the WebAssembly target possible

Fixed ​

  • thumbhash() was broken in the ESM build on Node - src/api/thumbhash.ts used require("zlib") inside a module bundled to ESM, which tsup rewrote into a "Dynamic require is not supported" throw. Bun tolerates require-in-ESM, so the bun-only test suite asserted dataUrl and still passed. Now a static import.
  • WebP images without an alpha channel failed to decode via decode_webp_fast. The code assumed the webp crate always returns RGBA, but it returns RGB (3 bytes/px) when there is no alpha, so the RGBA->RGB conversion built a buffer of the wrong length and every such decode failed with "Failed to create RGB image from WebP". The existing suite missed it because its WebP tests all pass target dimensions, which route through a different decoder.

Known limitations (WebAssembly only) ​

  • WebP output is lossless only (image has no lossy WebP encoder), so quality has no effect. JPEG quality is honoured.
  • No shrink-on-load, so thumbnailing decodes at full resolution first.
  • Async functions run on the calling thread, and timeoutMs is rejected rather than silently dropped.
  • Requires Node; Bun's node:wasi lacks initialize(). Bun users get the faster native addon anyway.
  • Requires emnapi@2.0.0-alpha.x; the 1.x line cannot link against napi-build 2.4.2.

[2.3.0] - 2026-06-23 ​

Added ​

  • Composite / Overlay / Watermark — New composite() / compositeSync() API for painting one or more layers onto a base image
    • Placement — gravity (center, southEast, …) with offsetX/offsetY, or absolute left/top coordinates (off-canvas/negative positions are clipped)
    • Blend modes — over (default), multiply, screen, overlay, darken, lighten, add
    • Per-layer opacity (0.0–1.0) and per-layer resize (scale a logo before compositing)
    • tile — repeat a layer across the whole base for watermark patterns
    • Multiple layers painted in order; output defaults to PNG (or set output for JPEG/PNG/WebP)
    • Full async support with timeoutMs / AbortSignal
    • See the Composite API and Composite & Watermark example

[2.2.1] - 2026-03-21 ​

Fixed ​

  • Native binding fails to load on macOS arm64 - Missing libheif.1.dylib (Issue #10)
    • Switched from dynamic linking to static linking for libheif via embedded-libheif
    • All HEIC/HEIF codec dependencies are now compiled from source and statically linked
    • No system-installed libheif or Homebrew dependencies required
    • Eliminates dylib version mismatches (e.g. libheif.1.dylib vs libheif.19.dylib)
    • See Issue #10 for details

[2.2.0] - 2026-02-17 ​

Added ​

  • Timeout & AbortSignal Support - All async functions now accept AsyncOptions (Issue #9)
    • timeoutMs — Rust-level timeout via tokio; rejects promise after specified duration
    • signal — JavaScript AbortSignal for programmatic cancellation
    • Works with AbortController, AbortSignal.timeout(), and custom abort reasons
    • Both options can be combined for maximum protection
    • Fully backward compatible
    • See Timeout & Cancellation API for details

[2.1.0] - 2026-01-25 ​

Added ​

  • Bun Single-File Executable Support - Native module now works with bun build --compile (Issue #8)

    • New imgkit-build CLI tool automates compilation with native module handling
    • Usage: bunx imgkit-build --compile --outfile dist/app src/index.ts
    • Automatic native module discovery from executable directory
    • No manual configuration required
    • See Bun Executables Guide for details
  • Enhanced Loader - Improved native module loading for Bun executables

    • Detects Bun single-file executables via $bunfs filesystem
    • Prioritizes executable directory for native module search
    • Context-aware error messages with specific guidance

[2.0.2] - 2026-01-25 ​

Fixed ​

  • Bun Native Binding Loading - Fixed native module loading on Bun runtime (Issue #7)
    • Added Bun runtime detection
    • Use globalThis.require for Bun's native module loading
    • Reordered loading strategies for better Bun compatibility
    • Fixes "Failed to load native binding" error on Bun 1.3.6+ with Apple Silicon

[2.0.1] - 2026-01-24 ​

Fixed ​

  • Windows Package Names - Renamed Windows packages to avoid npm spam detection
    • imgkit-win32-x64-msvc → imgkit-windows-x64
    • imgkit-win32-arm64-msvc → imgkit-windows-arm64
    • Windows users can now install imgkit without issues

[2.0.0] - 2026-01-19 ​

BREAKING CHANGES ​

  • Package Renamed - bun-image-turbo is now imgkit
    bash
    npm uninstall bun-image-turbo && npm install imgkit
    • All imports change from 'bun-image-turbo' to 'imgkit'
    • API is 100% compatible - no code changes needed beyond import path

Added ​

  • Fast Thumbnail Generation - Optimized thumbnail pipeline with shrink-on-load
    • thumbnail() / thumbnailSync() - Generate thumbnails with full metadata
    • thumbnailBuffer() / thumbnailBufferSync() - Generate thumbnails (buffer only)
    • Shrink-on-Load: JPEG decodes at 1/2, 1/4, 1/8 scale; WebP scales during decode
    • Fast Mode: Maximum speed with 2-4x improvement over normal mode
    • 4-10x faster than standard resize for large images

Performance ​

Method1MB JPEG10MB JPEGvs Sharp
thumbnail (shrinkOnLoad)9.1ms100ms1.2x faster
thumbnail (fastMode)9.1ms107ms1.2x faster
sharp10.9ms119msbaseline

Concurrent (100 images): 157ms total (1.6ms/img) - 1.9x faster than sharp

Test Results ​

  • 176 tests pass
  • All shrink-on-load optimizations verified

[1.9.1] - 2026-01-15 ​

Added ​

  • GitHub Community Standards - CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, issue templates

[1.9.0] - 2026-01-15 ​

Added ​

  • Native Smart Crop - Content-aware image cropping using saliency detection

    • smartCrop() / smartCropSync() - Automatically find and crop to the most interesting region
    • smartCropAnalyze() / smartCropAnalyzeSync() - Get optimal crop coordinates without cropping
    • Aspect Ratio Support:
      • 1:1 - Square (Instagram, profile pictures)
      • 16:9 - Landscape (YouTube, Twitter)
      • 9:16 - Portrait (Stories, TikTok)
      • 4:3, 3:2, 21:9 - And any custom ratio
    • Algorithm Features:
      • Saliency detection - Finds visually interesting areas
      • Edge detection - Preserves important details
      • Rule of thirds - Natural composition weighting
    • Use cases: Social media thumbnails, profile pictures, e-commerce product images
  • Dominant Color Extraction - Extract the most prominent colors from any image

    • dominantColors() / dominantColorsSync() - Get a palette of dominant colors
    • Returns RGB values and hex strings for each color
    • Configurable color count (default: 5 colors)
    • Result includes:
      • colors[] - Array of dominant colors sorted by prominence
      • primary - The most dominant color (convenience accessor)
      • Each color has: r, g, b (0-255) and hex ("#RRGGBB")
    • Use cases: UI theming, image placeholders, color palettes, accessibility

Why These Features Matter ​

Smart Crop automatically finds the best region - no manual coordinates needed:

  • Works with any aspect ratio
  • Finds faces, objects, and interesting content
  • Native Rust implementation using smartcrop2 crate

Dominant Colors enables dynamic UI theming:

  • Auto-theme UI based on images (like Spotify album art)
  • Generate color placeholders while images load
  • Create color palettes from photos
  • Native Rust implementation using dominant_color crate

Test Results ​

  • 150 tests pass (22 smart crop + 17 dominant colors)
  • All features verified with async and sync APIs
  • Works with JPEG, PNG, and WebP images

[1.8.0] - 2026-01-15 ​

Added ​

  • Native Perceptual Hashing - First JavaScript package with native SIMD-accelerated perceptual hashing for image similarity detection
    • imageHash() / imageHashSync() - Generate perceptual hash from any image
    • imageHashDistance() / imageHashDistanceSync() - Calculate hamming distance between hashes
    • 4 Hash Algorithms:
      • PHash - Perceptual hash using DCT (best for most use cases)
      • DHash - Difference hash using gradients (fast, good for similar images)
      • AHash - Average hash (fastest, least robust)
      • BlockHash - Block hash (good balance of speed and accuracy)
    • 3 Hash Sizes:
      • Size8 - 8x8 hash (64 bits) - fastest, good for most cases
      • Size16 - 16x16 hash (256 bits) - more accurate
      • Size32 - 32x32 hash (1024 bits) - highest accuracy
    • Use cases: Duplicate detection, content moderation, reverse image search, copyright detection

Why Perceptual Hashing Matters ​

Unlike cryptographic hashes (MD5, SHA), perceptual hashes allow similar images to have similar hashes:

  • Resized, compressed, or slightly modified images still match
  • Distance threshold: <5 = very similar, <10 = similar, >10 = different
  • Native Rust implementation is 10-50x faster than JavaScript alternatives

Test Results ​

  • 111 tests pass (24 new perceptual hash tests)
  • All algorithms (PHash, DHash, AHash, BlockHash) verified
  • Hash consistency and distance calculation tested

[1.7.9] - 2026-01-15 ​

Changed ​

  • Upgraded to napi-rs v3 - Major upgrade to the latest napi-rs framework
    • napi upgraded from v2 to v3.8.2
    • napi-derive upgraded from v2 to v3.5.1
    • @napi-rs/cli upgraded from v2.18.4 to v3.5.1
    • Enables future streaming features (ReadableStream, AsyncGenerator)
    • Better async/await patterns with improved lifetime management

Fixed ​

  • Added explicit #[derive(Clone)] to all string enums for napi-rs v3 compatibility
  • Removed deprecated napi.name field from package.json

Test Results ​

  • 87 tests pass - All existing functionality verified with napi-rs v3

[1.7.1] - 2026-01-13 ​

Added ​

  • ML Tensor Conversion - First JavaScript package with native SIMD-accelerated image-to-tensor conversion
    • toTensor() / toTensorSync() - Convert images to tensor format for ML frameworks
    • Built-in normalization presets:
      • Imagenet - ResNet, VGG, EfficientNet (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
      • Clip - CLIP, OpenCLIP, BLIP models (mean=[0.481, 0.458, 0.408], std=[0.269, 0.261, 0.276])
      • ZeroOne - Values in [0, 1] range
      • NegOneOne - Values in [-1, 1] range
    • Layout support:
      • Chw - Channel-first for PyTorch, ONNX Runtime
      • Hwc - Channel-last for TensorFlow.js
    • Data types: Float32 (default) and Uint8
    • Optional batch dimension for inference-ready tensors
    • Helper methods: toFloat32Array(), toUint8Array()

Performance ​

Benchmarks on Apple M3 Pro (800x600 JPEG input):

OperationTimeThroughput
224x224 ImageNet12.5ms80 img/s
224x224 Uint85.2ms192 img/s
384x384 ImageNet33.0ms30 img/s
1920x1080 → 224x22425.8ms39 img/s

10-16x faster than JavaScript-based alternatives!

Why This Matters ​

  • No manual normalization - Built-in presets for popular models
  • SIMD optimization - Native Rust with parallel channel processing via Rayon
  • Shrink-on-load - Large images downscaled during decode
  • Zero-copy - Minimal memory allocations
  • Type-safe - Full TypeScript support with proper types

Test Results ​

  • 87 tests pass (10 new toTensor tests)
  • All normalization presets verified
  • Both layouts (CHW/HWC) and dtypes (Float32/Uint8) tested

[1.6.0] - 2026-01-13 ​

Added ​

  • Cropping API - Zero-copy image cropping with multiple modes
    • crop() / cropSync() - Extract regions from images
    • Three cropping modes:
      • Explicit coordinates: { x: 100, y: 50, width: 400, height: 300 }
      • Aspect ratio: { aspectRatio: "16:9" } or { aspectRatio: "1:1" }
      • Dimensions with gravity: { width: 500, height: 500, gravity: "Center" }
    • 9 gravity options: Center, North, South, East, West, NorthWest, NorthEast, SouthWest, SouthEast
    • Crop support in transform() pipeline - crop is applied first for maximum performance

Performance ​

  • Zero-copy cropping using crop_imm() - essentially free operation (just pointer arithmetic)
  • Optimized transform pipeline - crop → resize order reduces pixels for subsequent operations
  • Improved brightness adjustment - replaced manual loop with optimized brighten() builtin (5x faster)
  • ThumbHash shrink-on-load - decode at 100x100 max before hash generation

Code Quality ​

  • Added #[inline(always)] to hot encode functions
  • Cleaner transform pipeline with crop-first architecture

Test Results ​

  • 64 tests pass (8 new crop tests, 2 new transform+crop tests)
  • All async and sync functions verified

[1.5.0] - 2026-01-10 ​

Added ​

  • ThumbHash Support - Generate smoother, more visually pleasing image placeholders
    • thumbhash() / thumbhashSync() - Generate ThumbHash from any image
    • thumbhashToRgba() / thumbhashToRgbaSync() - Decode ThumbHash to RGBA pixels
    • thumbhashToDataUrl() - Convert ThumbHash to data URL for inline use
    • Returns ready-to-use dataUrl for immediate display in HTML/CSS

ThumbHash vs BlurHash ​

FeatureThumbHashBlurHash
Alpha channel✅ Yes❌ No
Aspect ratio preserved✅ Yes❌ No
Color accuracyBetterGood
Hash size~25 bytes~28 chars

Test Results ​

  • 56 tests pass (including 12 new ThumbHash tests)
  • All async and sync functions verified

[1.4.6] - 2026-01-09 ​

Added ​

  • Comprehensive Test Suite - Reorganized test structure
    • test/local/ - Local development tests
    • test/packages/ - Package manager verification (bun, npm, yarn, pnpm)

Verified ​

  • All Package Managers Working:
    • Bun: 39 tests pass ✅
    • npm: 32 tests pass ✅
    • yarn: 32 tests pass ✅
    • pnpm: 32 tests pass ✅

[1.4.5] - 2026-01-09 ​

Fixed ​

  • ESM/CJS Native Binding Loading - Fixed native module loading in Node.js ESM context
    • Use createRequire(import.meta.url) for ESM modules
    • Proper fallback to native require for CJS context
    • Fixes "Cannot find package" errors when using import in Node.js

[1.4.0] - 2026-01-08 ​

Added ​

  • WebP Shrink-on-Load Optimization - Decode WebP images directly to target resolution
    • Uses libwebp's native use_scaling for 1.15-1.25x faster WebP resize operations
    • Memory usage scales with OUTPUT size, not INPUT size (up to 25x reduction)

Performance ​

  • WebP Resize now 1.15-1.25x faster than sharp on average
  • Zero-copy pipeline reduces memory copies from 3-5 to 1-2 per operation

Fixed ​

  • Issue #3: WebP resize slower than sharp - Now faster!
  • Issue #3: macOS requires libheif for WebP - CI only installs libheif for ARM64
  • Issue #3: Linux installation fails - Added optionalDependencies

[1.3.1] - 2026-01-08 ​

Changed ​

  • Code Reorganization - Refactored codebase for better maintainability
    • Split rust/src/decode.rs into modular decode/ and metadata/ directories
    • Extracted Rust types to rust/src/types.rs
    • Split src/index.ts into loader.ts, converters.ts, and api/ modules
    • No API changes - all functionality preserved
  • Removed unused code and fixed Rust compiler warnings

[1.3.0] - 2026-01-07 ​

Added ​

  • EXIF Metadata Writing - Write EXIF metadata to JPEG and WebP images
    • writeExif() / writeExifSync() - Add EXIF metadata to images
    • stripExif() / stripExifSync() - Remove all EXIF metadata from images
    • Perfect for AI-generated image attribution and metadata embedding
    • Supports: ImageDescription, Artist, Copyright, Software, DateTime, UserComment, Make, Model, Orientation
    • Use transform() with exif option to add metadata during processing

Technical Details ​

  • Added img-parts crate for EXIF chunk manipulation
  • EXIF data built using proper TIFF/IFD0 structure
  • UserComment field supports JSON storage for AI generation parameters
  • Full async and sync API support

[1.2.2] - 2025-12-12 ​

Documentation ​

  • New Architecture Guide - Deep dive into tech stack, processing pipeline, and key optimizations
  • Fixed resize() documentation - Clarified that output is always PNG format
  • Fixed transform() documentation - output is optional (defaults to PNG), added GIF/BMP examples
  • Fixed formats guide - Removed non-existent toGif(), use transform() instead
  • Enhanced performance guide - Added technical details about shrink-on-decode, multi-step resize, and adaptive algorithm selection
  • Updated API reference - Added version() function documentation
  • Fixed platform support tables - All platforms are supported, HEIC only on macOS ARM64
  • Added VitePress documentation site - Professional docs with GitHub Pages deployment

Fixed ​

  • ESM module configuration for VitePress 1.6+

[1.2.0] - 2024 ​

Added ​

  • HEIC/HEIF Support - Native support for Apple's modern image format (macOS ARM64)
  • Blurhash Generation - Create compact image placeholder strings
  • AVIF Support - Read AVIF images via libheif

Changed ​

  • Improved metadata extraction performance (950x faster for WebP)
  • Better error messages for unsupported formats

Platform Support ​

  • macOS ARM64 (M1/M2/M3/M4/M5) - Full support including HEIC
  • macOS x64 (Intel) - Full support except HEIC
  • Linux x64 (glibc) - Full support except HEIC
  • Linux x64 (musl/Alpine) - Full support except HEIC
  • Linux ARM64 (glibc) - Full support except HEIC
  • Windows x64 - Full support except HEIC
  • Windows ARM64 - Full support except HEIC

[1.1.0] - 2024 ​

Added ​

  • transform() function for multi-operation pipelines
  • Brightness and contrast adjustments
  • Blur and sharpen effects
  • Sync versions of all functions

Improved ​

  • Resize quality with lanczos3 filter
  • Memory usage optimization
  • Better TypeScript types

[1.0.0] - 2024 ​

Initial Release ​

  • metadata() - Fast image metadata extraction
  • resize() - High-quality image resizing
  • toJpeg() - JPEG encoding with TurboJPEG
  • toPng() - PNG encoding
  • toWebp() - WebP encoding (lossy and lossless)
  • Grayscale conversion
  • Rotation (90, 180, 270 degrees)
  • Horizontal and vertical flip

Supported Formats ​

  • JPEG (read/write)
  • PNG (read/write)
  • WebP (read/write)
  • GIF (read/write)
  • BMP (read/write)
  • TIFF (read)
  • ICO (read)