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 🙏

© 2026 – Pkg Stats / Ryan Hefner

jl-optimize-images

v1.0.1

Published

Pure TypeScript image compression library with zero framework dependencies

Readme

jl-optimize-images 🚀

npm version License: MIT TypeScript Zero Dependencies GitHub Repository

Ultra-fast, zero-dependency in-browser image compression engine for TypeScript and JavaScript. Hardware-accelerated GPU decoding via ImageBitmap, automatic EXIF rotation, step-down downscaling, and non-blocking UI batch processing (yieldToMain).


🔗 Quick Links & Live Demos

| Resource | URL | | :--- | :--- | | 🌐 Interactive Documentation | https://jl-image-manger.vercel.app/app/documentation/ | | ⚡ Live Playground | https://jl-image-manger.vercel.app/app/playground/ | | 🐙 GitHub Repository | https://github.com/cjorgeluis122333/jl-image-manger |


📋 Table of Contents


✨ Features

  • 📦 Zero External Dependencies: Lightweight native library built strictly on modern Canvas API and Web APIs.
  • Hardware-Accelerated GPU Cache (ImageBitmap): Decodes the image once into GPU memory. Real-time adjustments (e.g. quality sliders) execute in milliseconds without re-decoding from disk.
  • 📸 Automatic EXIF Orientation: Natively corrects photo orientation from mobile devices and digital cameras via createImageBitmap(blob, { imageOrientation: 'from-image' }).
  • 📉 Fractional Step-Down Scaling: Progressive halving downscaling algorithm that eliminates aliasing artifacts (jagged pixels) and maintains maximum sharpness.
  • 🟢 Smooth 60 FPS UI Thread Preservation (yieldToMain): Prevents browser freeze during heavy batch operations by yielding execution control to the event loop (scheduler.yield() or MessageChannel).
  • 🎨 Multi-Format Export: Native conversion support for image/webp, image/jpeg, and image/png.
  • ⚙️ Dimension & Quality Controls: Custom target quality, maximum width/height constraints, aspect ratio locking, and custom background fill colors for transparent images.
  • 📊 Instant Metrics & Analytics: Immediate feedback on byte sizes (original vs compressed) and percentage savings.

💡 Why jl-optimize-images?

Compressing images directly in the browser before sending them to a server saves up to 80-90% of upload bandwidth, improves mobile user experience, reduces cloud storage costs, and speeds up form submissions.

Traditional image compression libraries often cause UI stuttering or loss of sharpness during extreme resolution reduction. jl-optimize-images addresses these challenges with GPU decoding memory caching, non-blocking asynchronous yielding, and step-down canvas scaling.


📥 Installation

Install the package via your preferred package manager:

npm install jl-optimize-images

Or using yarn, pnpm, or bun:

# Yarn
yarn add jl-optimize-images

# pnpm
pnpm add jl-optimize-images

# Bun
bun add jl-optimize-images

🚀 Quick Start

import { ImageCompressor } from 'jl-optimize-images';

// 1. Get image file from an input element
const fileInput = document.querySelector<HTMLInputElement>('#upload')!;
const file = fileInput.files![0];

// 2. Instantiate ImageCompressor
const compressor = new ImageCompressor(file);

// 3. (Optional but recommended) Pre-load into GPU memory for ultra-fast performance
await compressor.preload();

// 4. Compress to WebP at 85% quality
const result = await compressor.compress({
  quality: 0.85,
  mimeType: 'image/webp',
  maxWidth: 1200,
});

// 5. Inspect analytics & use output
console.log(`Original: ${(result.originalSize / 1024).toFixed(1)} KB`);
console.log(`Compressed: ${(result.compressedSize / 1024).toFixed(1)} KB`);
console.log(`Saved: ${result.savingsPercentage.toFixed(1)}%`);

// Display preview immediately
document.querySelector<HTMLImageElement>('#preview')!.src = result.dataUrl;

// 6. Release graphics memory when finished
compressor.dispose();

🛠️ Advanced Usage

1. Avatar Optimization (400x400)

const avatarResult = await compressor.compress({
  maxWidth: 400,
  maxHeight: 400,
  quality: 0.8,
  mimeType: 'image/webp',
  maintainAspectRatio: true,
});

2. Transparent PNG to White JPEG Conversion

When converting transparent PNGs to JPEG format, fill transparent pixels with a solid background color to avoid black backgrounds:

const jpegResult = await compressor.compress({
  quality: 0.85,
  mimeType: 'image/jpeg',
  backgroundColor: '#ffffff', // Fills transparent alpha channel with white
});

3. Concurrent Batch Processing

Process multiple images in parallel with controlled concurrency to prevent thread contention:

import { compressBatch } from 'jl-optimize-images';

const fileList = fileInput.files!; // FileList or File[]

const batchResults = await compressBatch(fileList, {
  quality: 0.8,
  mimeType: 'image/webp',
  maxWidth: 1920,
  concurrency: 3, // Process 3 images concurrently
});

batchResults.forEach((res, index) => {
  console.log(`Image ${index + 1}: ${res.savingsPercentage.toFixed(1)}% saved`);
});

📖 API Reference

ImageCompressor Class

export class ImageCompressor {
  constructor(source: File | Blob);

  /**
   * Pre-loads and decodes the image into an ImageBitmap in GPU cache.
   */
  preload(): Promise<void>;

  /**
   * Compresses the image using the provided compression options.
   */
  compress(options?: CompressionOptions): Promise<CompressionResult>;

  /**
   * Releases stored ImageBitmap memory cache.
   */
  dispose(): void;
}

CompressionOptions

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | quality | number | 0.85 | Compression quality rating between 0.01 and 1.0. | | maxWidth | number | undefined | Maximum width constraint in pixels. | | maxHeight | number | undefined | Maximum height constraint in pixels. | | mimeType | 'image/webp' \| 'image/jpeg' \| 'image/png' | 'image/webp' | Target output image format. | | maintainAspectRatio | boolean | true | Preserves width/height ratio during resizing. | | backgroundColor | string | undefined | Solid color (e.g., '#ffffff') to replace transparent alpha channel when converting to formats like JPEG. |

CompressionResult

export interface CompressionResult {
  file: File;                // Compressed File object ready for FormData / fetch upload
  dataUrl: string;           // Base64 Data URL string for immediate browser rendering
  originalSize: number;      // Input size in bytes
  compressedSize: number;    // Output size in bytes
  savingsPercentage: number;  // Weight reduction percentage (0% to 100%)
}

compressBatch Function

export function compressBatch(
  files: FileList | File[],
  options?: CompressionOptions & { concurrency?: number }
): Promise<CompressionResult[]>;

🌐 Browser Compatibility

jl-optimize-images is compatible with all modern web browsers supporting HTML5 Canvas API and ImageBitmap:

  • Chrome / Edge: 79+
  • Firefox: 84+
  • Safari: 15+
  • Opera: 66+
  • iOS Safari / Android Chrome: Supported

🏷️ Keywords

image compression client-side image compressor browser image optimization webp converter exif auto rotation imagebitmap gpu decoding typescript image resizer javascript image compress canvas image resize batch image compression vanilla js image optimizer


📄 License

MIT © Jorge Luis Pabón Izquierdojl-image-manger Repository