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

quickpix

v0.2.0

Published

High-performance image resize for browsers and Node.js. Rust/WASM accelerated, zero dependencies, pure JS fallback.

Readme

quickpix

npm version npm bundle size zero dependencies license

한국어

High-performance image resize for browsers and Node.js. Rust/WASM accelerated with pure JS fallback. Zero dependencies.

npm install quickpix

Quick Start — High-Level API (QuickPixEasy)

For most use cases, QuickPixEasy is all you need. Blob/File in → resize → Blob out, in a single call.

import { QuickPixEasy } from "quickpix";

const qp = new QuickPixEasy({
  filter: "lanczos",           // resize filter (default: bilinear)
  outputMimeType: "image/jpeg",
  outputQuality: 0.85,
  preserveMetadata: true,      // preserve EXIF/ICC/IPTC metadata
  autoRotate: true,            // auto-correct EXIF orientation (default: true)
});

Resize Blob/File

const input = document.querySelector('input[type="file"]');
const file = input.files[0];

// Exact dimensions
const resized = await qp.resizeBlob(file, 1200, 800);

// Width only — height auto-calculated (aspect ratio preserved)
const resized2 = await qp.resizeBlob(file, 1200, null);

// Height only — width auto-calculated
const resized3 = await qp.resizeBlob(file, null, 800);

// Max dimension — longest side fits within limit
const resized4 = await qp.resizeBlob(file, null, null, { maxDimension: 4096 });

// resizeFile is an alias for resizeBlob
const resized5 = await qp.resizeFile(file, 1200, null);

Create Thumbnails

Automatically preserves aspect ratio. The longest side fits within maxDimension.

// 6000x4000 image → 200x133 thumbnail
const thumbnail = await qp.createThumbnail(file, 200);

// Also accepts Canvas, ImageData, HTMLImageElement
const thumb2 = await qp.createThumbnail(canvasElement, 150);

Draw to Canvas

const canvas = document.getElementById("preview");
canvas.width = 800;
canvas.height = 600;

await qp.resizeToCanvas(file, canvas, { filter: "lanczos" });

Batch Parallel Processing

Processes multiple images concurrently using a Web Worker pool. Each image runs the full decode→resize→encode pipeline in a separate worker.

const results = await qp.batchResize([
  { source: photo1, maxDimension: 800 },
  { source: photo2, width: 600, height: 400 },
  { source: photo3, maxDimension: 200 },
]);
// results = [Blob, Blob, Blob]

Metadata Preservation

By default, Canvas API strips all EXIF, ICC profiles, and other metadata. Set preserveMetadata: true to re-inject the original JPEG metadata into the output.

// Preserve metadata (EXIF date, GPS, camera info, ICC color profile, etc.)
const withMeta = await qp.resizeBlob(photo, 1200, 800, {
  preserveMetadata: true,
  outputMimeType: "image/jpeg",
});

// Strip metadata (default — better for privacy)
const stripped = await qp.resizeBlob(photo, 1200, 800, {
  preserveMetadata: false,
});

EXIF Orientation Auto-Correction

Smartphone photos store rotation info in EXIF. With autoRotate: true (default), images are automatically corrected to the right orientation.

// autoRotate: true (default) — portrait photos display correctly
const rotated = await qp.resizeBlob(phonePhoto, 800, 600);

// autoRotate: false — keep original pixel orientation
const raw = await qp.resizeBlob(phonePhoto, 800, 600, { autoRotate: false });

Fit Modes

// contain (default): fit within 800x600, preserve aspect ratio
const a = await qp.resizeBlob(photo, 800, 600, { fit: "contain" });

// cover: fill 800x600 completely, preserve aspect ratio (may crop)
const b = await qp.resizeBlob(photo, 800, 600, { fit: "cover" });

// fill: stretch to exactly 800x600, ignore aspect ratio
const c = await qp.resizeBlob(photo, 800, 600, { fit: "fill" });

Cleanup

qp.destroy(); // terminate worker pool and release resources

Options Reference

| Option | Default | Description | |---|---|---| | filter | "bilinear" | Resize filter (nearest, bilinear, box, hamming, lanczos) | | maxWorkers | navigator.hardwareConcurrency | Max worker pool size | | idleTimeout | 30000 | Auto-terminate idle workers (ms) | | outputMimeType | "image/png" | Output image format | | outputQuality | 0.92 | JPEG/WebP quality (0–1) | | useWasm | true | Enable WASM acceleration | | preserveMetadata | false | Preserve EXIF/ICC/IPTC metadata | | autoRotate | true | Auto-correct EXIF orientation | | workerURL | null | Optional override: worker URL or factory for environments that cannot resolve import.meta.url worker imports | | requireWorker | false | If true, throws when worker pipeline is unavailable instead of falling back to main thread | | wasmPath | null | Override WASM module URL |


Low-Level API (QuickPix)

For direct RGBA buffer manipulation or fine-grained control.

import { QuickPix } from "quickpix";

const qp = new QuickPix({ useWasm: true, filter: "lanczos" });

const src = new Uint8ClampedArray(640 * 480 * 4);
const out = await qp.resizeBuffer(src, 640, 480, 320, 240, {
  filter: "lanczos",
});

console.log(out.width, out.height, out.data.length); // 320 240 307200

Bundler-safe worker setup (Next, Vite, Rollup, esbuild, webpack, Turbopack)

QuickPix and QuickPixEasy now try worker imports from multiple internal candidate paths first, so most projects work without workerURL.

import { QuickPix, QuickPixEasy } from "quickpix";

const qp = new QuickPix();
const qpe = new QuickPixEasy();

If your bundler still fails to locate workers, pass workerURL in manually and keep requireWorker: true for hard-fail behavior:

import { QuickPix, QuickPixEasy } from "quickpix";
import resizeWorkerURL from "quickpix/resize-worker.js?url";
import pipelineWorkerURL from "quickpix/pipeline-worker.js?url";

const qp = new QuickPix({
  workerURL: resizeWorkerURL,
  requireWorker: true,
});

const qpe = new QuickPixEasy({
  workerURL: pipelineWorkerURL,
  requireWorker: true,
});

Example bundler templates are in examples/bundlers.

Supported Filters

| Filter | Description | Speed | Quality | |---|---|---|---| | nearest | Nearest neighbor | Fastest | Low | | bilinear | 2x2 linear interpolation (default) | Fast | Medium | | box | Box average | Medium | Medium | | hamming | Hamming window | Slow | High | | lanczos | Lanczos3 sinc-based | Slowest | Best |


Metadata Module

Standalone module for direct EXIF/ICC/IPTC manipulation.

import { readOrientation, extractSegments, injectSegments } from "quickpix/metadata";

const buffer = await file.arrayBuffer();
const orientation = readOrientation(buffer);
const segments = extractSegments(buffer);
const restored = await injectSegments(resizedJpegBlob, segments);

Install & Build

npm install quickpix

# Development (build from source)
npm install
npm run build:wasm    # Rust → WASM (requires wasm-pack)
npm run test:js
npm run test:rust

Benchmarks

npm run bench           # performance
npm run bench:compare   # vs pica
npm run bench:memory    # memory profiling
npm run bench:native    # vs sharp (libvips)
npm run bench:quality   # quality comparison

Browser Compatibility

| Feature | Chrome 69+ | Firefox 105+ | Safari 16.4+ | |---|---|---|---| | Pipeline worker (optimal) | Yes | Yes | Yes | | JS fallback | All browsers | All browsers | All browsers |

Automatically falls back to main-thread processing when OffscreenCanvas is unavailable.

License

MIT