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

@blazediff/core-wasm

v4.3.3

Published

WebAssembly build of blazediff for browsers, edge runtimes, and any wasm host. Same algorithm as @blazediff/core-native.

Readme

@blazediff/core-wasm

npm bundle size NPM Downloads Crates.io

WebAssembly build of the BlazeDiff Rust algorithm for browsers, edge runtimes, and any wasm host. Same two-pass block algorithm as @blazediff/core-native, compiled to wasm32 with v128 SIMD (+simd128). ~58% faster than pixelmatch on the same RGBA buffers; diff counts agree with pixelmatch to within ~0.05%.

Features:

  • Same Rust algorithm as @blazediff/core-native (YIQ perceptual delta + block-based cold/hot pass)
  • wasm32 v128 SIMD: 4-lane vectorized cold and hot loops; up to ~16x faster than pixelmatch on 4K
  • Buffers-only API: caller decodes images, hands in Uint8Array. No PNG/JPEG codecs bundled
  • ~32 KB optimized wasm + ~10 KB JS glue. No native binaries, no postinstall, no platform packages
  • Runs anywhere wasm runs: browsers, Node 18+, Cloudflare Workers, Deno, Bun

Installation

npm install @blazediff/core-wasm

Loading the wasm module

Pick the recipe that matches your runtime. All four are equivalent; the wasm itself is the same.

Browser (default fetch)

The wasm-bindgen --target web glue fetches the sibling .wasm via import.meta.url automatically:

import { initBlazediff } from '@blazediff/core-wasm';
await initBlazediff();

Universal CDN URL (recommended for Node, Workers, Deno, Bun)

jsDelivr serves the published .wasm over HTTPS, so any fetch()-capable runtime can load it. One network round-trip on cold start, cached by the runtime after that:

import { initBlazediff } from '@blazediff/core-wasm';

await initBlazediff(
  new URL(
    'https://cdn.jsdelivr.net/npm/@blazediff/[email protected]/wasm/blazediff_bg.wasm',
  ),
);

Pin the version (@4.2.0) for reproducibility. unpkg.com/@blazediff/[email protected]/wasm/blazediff_bg.wasm works identically.

Bundlers (Vite, Webpack 5+, esbuild, Rollup with plugin)

The new URL(asset, import.meta.url) pattern is bundler-aware: the asset is emitted into the build output and the URL is rewritten at build time:

import { initBlazediff } from '@blazediff/core-wasm';

const wasmUrl = new URL(
  '@blazediff/core-wasm/wasm/blazediff_bg.wasm',
  import.meta.url,
);
await initBlazediff(wasmUrl);

Node from the local filesystem

Offline, no CDN dependency. Read the bytes and pass them in:

// ESM (Node 20.6+):
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { initBlazediff } from '@blazediff/core-wasm';

const wasmPath = fileURLToPath(
  import.meta.resolve('@blazediff/core-wasm/wasm/blazediff_bg.wasm'),
);
await initBlazediff(readFileSync(wasmPath));
// CommonJS:
const { readFileSync } = require('node:fs');
const { initBlazediff } = require('@blazediff/core-wasm');

const wasmPath = require.resolve(
  '@blazediff/core-wasm/wasm/blazediff_bg.wasm',
);
await initBlazediff(readFileSync(wasmPath));

API

initBlazediff(input?)

Initializes the wasm module. Safe to call multiple times; subsequent calls return the cached promise. Accepts a URL, Response, ArrayBuffer, Uint8Array, or compiled WebAssembly.Module. Without input, the default --target web glue fetches the sibling blazediff_bg.wasm via import.meta.url (works in browsers; other runtimes need an explicit input, see above).

Returns: Promise<void>

diff(a, b, width, height, output?, options?)

Compares two RGBA pixel buffers and returns the number of differing pixels.

Returns: Promise<number> (count of differing pixels)

Usage

Browser

Decode images via createImageBitmap + OffscreenCanvas (or the ImageDecoder API), then pass the RGBA buffer to diff():

import { diff, initBlazediff } from '@blazediff/core-wasm';

await initBlazediff();

async function toRgba(url: string) {
  const bitmap = await createImageBitmap(await (await fetch(url)).blob());
  const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
  const ctx = canvas.getContext('2d')!;
  ctx.drawImage(bitmap, 0, 0);
  const { data } = ctx.getImageData(0, 0, bitmap.width, bitmap.height);
  return { data: new Uint8Array(data.buffer), width: bitmap.width, height: bitmap.height };
}

const a = await toRgba('/baseline.png');
const b = await toRgba('/current.png');
const out = new Uint8Array(a.width * a.height * 4);

const diffCount = await diff(a.data, b.data, a.width, a.height, out, {
  threshold: 0.1,
});

console.log(`${diffCount} pixels differ`);

Node

import { readFileSync } from 'node:fs';
import { diff, initBlazediff } from '@blazediff/core-wasm';
import { PNG } from 'pngjs';

await initBlazediff(
  new URL(
    'https://cdn.jsdelivr.net/npm/@blazediff/[email protected]/wasm/blazediff_bg.wasm',
  ),
);

const a = PNG.sync.read(readFileSync('baseline.png'));
const b = PNG.sync.read(readFileSync('current.png'));
const diffCount = await diff(
  new Uint8Array(a.data),
  new Uint8Array(b.data),
  a.width,
  a.height,
);

Performance

vs pixelmatch on M1 Max, image I/O excluded (pre-decoded RGBA buffers):

| Fixture | pixelmatch | core-wasm | Improvement | |---------------|------------|-----------|-------------| | 4k/1 | 287.72ms | 51.75ms | 82.0% | | 4k/3 | 366.81ms | 69.90ms | 80.9% | | page/2 | 443.83ms | 109.74ms | 75.3% | | blazediff/3 | 14.60ms | 5.52ms | 62.2% | | pixelmatch/1 | 0.87ms | 0.13ms | 84.6% |

Average ~58% faster across the full fixture set. Counts agree with pixelmatch within ~0.05% (e.g. 4k/1: 69 932 vs 69 912 of 17 920 000 pixels). Full benchmarks in BENCHMARKS.md.

Algorithm

Same two-pass block-based approach as @blazediff/core-native, recompiled for wasm:

  1. Cold pass: scans the image in 8x8 blocks using 32-bit integer comparison to identify changed regions
  2. Hot pass: only processes blocks marked as changed, applying YIQ perceptual color difference
  3. SIMD: v128 intrinsics (f32x4_*, i32x4_*) for parallel 4-lane RGBA extraction, alpha blend, YIQ transform, and threshold compare. Baseline simd128 has no native FMA, so weighted sums use add(mul, c)
  4. Anti-aliasing: Vysniauskas (2009) algorithm to detect AA artifacts

Picking the right package

| Use case | Package | |-----------------------------------|-------------------------------------------------------------------------------| | Browser, edge worker, wasm host | @blazediff/core-wasm | | Node CLI / server with native bin | @blazediff/core-native | | Pure JS / no wasm support | @blazediff/core |

References