@blazediff/core-native

中文文档
7.0.0发布于 2026/11/05MITTypeScriptESM + CJS构建来源已验证近 30 天下载 2万

Native Rust binaries for blazediff - the fastest image diff in the world

原始使用文档
文档目录14 节
  1. Installation
  2. API
  3. diff(a, b, options?)
  4. Result Types
  5. Usage
  6. Programmatic API
  7. Describing What Changed
  8. CLI Usage
  9. CLI Options
  10. Supported Formats
  11. Exit Codes
  12. Performance
  13. Algorithm
  14. References

@blazediff/core-native

npm bundle size NPM Downloads Crates.io

The fastest single-threaded image diff in the world. Native Rust implementation with SIMD optimization, 4.4-4.9x faster and 3x smaller than odiff.

Features:

  • PNG, JPEG & QOI support - auto-detected by file extension or encoded bytes
  • SIMD-accelerated (NEON on ARM, SSE4.1 on x86)
  • Block-based two-pass optimization
  • YIQ perceptual color difference
  • Anti-aliasing detection
  • Cross-platform pre-built binaries (~700KB-900KB, no compilation required)

Vendored Libraries:

  • libspng - Fast PNG decoding/encoding with SIMD (default)
  • libjpeg-turbo - High-performance JPEG codec with SIMD
  • qoi - QOI (Quite OK Image) format for fast lossless compression

Experimental PNG codec: the binaries also bundle an in-house Rust PNG codec (blazediff-png), faster than spng on every fixture with byte-exact decode parity. It's opt-in: set BLAZEDIFF_PNG_ENABLED=1 to route PNG decode and stored-block (level 0) encode through it. spng stays the default.

Note: This package was previously published as @blazediff/bin, which is now deprecated. Please use @blazediff/core-native instead.

Installation

npm install @blazediff/core-native

Also available as a Rust crate: cargo install blazediff

Pre-built binaries are included via platform-specific packages:

API

diff(a, b, options?)

Compare two images and optionally draw the diff. options is @blazediff/core's DiffOptions, with a wider output.

Parameter Type Description
a, b string | Uint8Array | Image A file path, encoded PNG, JPEG or QOI bytes (a Buffer works), or raw RGBA pixels { data, width, height }. The two sides can use different kinds
options NativeDiffOptions Comparison options (optional)

Returns: Promise<NativeDiffResult>

Option Type Default Description
threshold number 0.1 Color difference threshold (0-1). Lower is stricter
antialiasing boolean true Detect anti-aliased pixels and leave them out of the count
metric "yiq" | "oklab" "yiq" Color difference metric. oklab gives the same counts as pixelmatch 8
mask Uint8Array - One byte per pixel (width × height). Non-zero pixels are skipped. Needs the N-API binding
window number - Also report the N×N window with the most diff pixels
output string | Image | { path, compression?, quality? } - Where to draw the diff: a file (PNG compression 0-9, JPEG quality 1-100), or an Image filled in place. A file is not written when the images are identical. An Image is always filled
render { alpha?, diffColor?, diffColorAlt?, aaColor?, background? } - Output styling. background: "transparent" draws the diff alone

Result Types

type NativeDiffResult =
  | {
      kind: "compared";
      count: number;
      percentage: number;
      identical: boolean;
      /** Top-left corner and count of the busiest window, when `window` is set. */
      window?: { x: number; y: number; count: number };
    }
  | { kind: "dimension-mismatch"; a: Size; b: Size }
  | { kind: "io-error"; path?: string; message: string };

Invalid options or buffers throw a BlazeDiffError (re-exported from @blazediff/core) with a code: invalid-image, invalid-output, invalid-mask or invalid-option.

Encoded Buffer Inputs

import { readFile } from "node:fs/promises";
import { diff } from "@blazediff/core-native";

const [expected, actual] = await Promise.all([
  readFile("expected.png"),
  readFile("actual.png"),
]);

const result = await diff(expected, actual, { output: "diff.png" });

The native binding borrows the existing Buffer or Uint8Array backing memory for the synchronous call. The encoded bytes are not copied into Rust, so the same JavaScript buffers can be reused across comparisons. Decoding still allocates native RGBA pixel buffers.

CLI fallback

If the N-API binding cannot load, diff runs the bundled blazediff CLI. The fallback takes path inputs and a path output only, and no mask. Anything else throws.

Usage

Programmatic API

import { diff } from '@blazediff/core-native';

const result = await diff('expected.png', 'actual.png', {
  output: 'diff.png',
  threshold: 0.1,
});

if (result.kind === 'compared') {
  if (result.identical) console.log('Images are identical!');
  else console.log(`${result.count} pixels differ (${result.percentage.toFixed(2)}%)`);
} else if (result.kind === 'dimension-mismatch') {
  console.log('Images have different dimensions');
} else {
  console.log(`Could not read ${result.path}: ${result.message}`);
}

Describing What Changed

This package answers where two images differ. For what changed — labelled regions, change types, severity and a human-readable summary — use @blazediff/interpret-native, which classifies the same diff and can also locate regions with an SSIM map or boxes you already have.

import { interpret } from '@blazediff/interpret-native';

const result = await interpret('expected.png', 'actual.png', 'diff.png');
console.log(result.summary);
console.log(`Severity: ${result.severity}, ${result.diffPercentage.toFixed(2)}% changed`);

CLI Usage

# Compare two PNG images
npx blazediff expected.png actual.png -o diff.png

# Compare two JPEG images
npx blazediff expected.jpg actual.jpg -o diff.jpg

# Mixed formats (PNG input, QOI output - recommended for smallest diff files)
npx blazediff expected.png actual.png -o diff.qoi

# With options
npx blazediff expected.png actual.png -o diff.png --threshold 0.05 --no-antialiasing

# pixelmatch 8 metric, a mask, and the busiest 16×16 window
npx blazediff expected.png actual.png --metric oklab --mask mask.png --window 16

# With higher PNG compression (smaller output file, slower)
npx blazediff expected.png actual.png -o diff.png -c 6

# Output as JSON
npx blazediff expected.png actual.png --json

CLI Options

Usage: blazediff [OPTIONS] <A> <B>

Arguments:
  <A>  First image path (PNG, JPEG, or QOI)
  <B>  Second image path (PNG, JPEG, or QOI)

Options:
  -o, --output <OUTPUT>                  Write the diff image (only when the images differ)
  -t, --threshold <THRESHOLD>            Color difference threshold (0.0-1.0) [default: 0.1]
      --antialiasing                     Detect anti-aliased pixels and leave them out of the count (default)
      --no-antialiasing                  Count anti-aliased pixels as differences
      --metric <METRIC>                  Color difference metric: yiq or oklab (pixelmatch 8) [default: yiq]
      --mask <MASK>                      Image the size of the inputs; its non-black pixels are skipped
      --window <WINDOW>                  Also report the N×N window with the most diff pixels
  -a, --alpha <ALPHA>                    Opacity of the faded background (0.0-1.0) [default: 0.1]
      --diff-color <R,G,B>               RGB color for differing pixels
      --diff-color-alt <R,G,B>           RGB color for pixels that get darker in the second image
      --aa-color <R,G,B>                 RGB color for anti-aliased pixels
      --background <BACKGROUND>          faded or transparent [default: faded]
  -c, --compression <COMPRESSION>        PNG compression level (0-9, 0=fastest, 9=smallest) [default: 0]
  -q, --quality <QUALITY>                JPEG quality (1-100) [default: 90]
      --json                             Print the result as JSON
  -h, --help                             Print help
  -V, --version                          Print version

With --json, the result object prints to stdout and an error such as {"kind":"io-error","path":"...","message":"..."} prints to stderr.

Supported Formats

FormatExtensionsNotes
PNG.pngLossless, supports transparency
JPEG.jpg, .jpegLossy, smaller file sizes
QOI.qoiFast lossless, ideal for diff outputs (12x smaller than uncompressed PNG)

Input images can be mixed formats (e.g., compare PNG to JPEG). Output format is determined by the output file extension.

QOI for diff outputs: QOI excels at encoding diff images with large uniform areas, producing files 12x smaller than PNG (level 0) while being faster to encode.

Exit Codes

  • 0 - Images are identical
  • 1 - Images differ, or their dimensions do not match
  • 2 - Error (file not found, invalid format, etc.)

Performance

Benchmarked on Apple M1 Max (25 runs, 5 warmup, image IO included) against odiff on 5600×3200 4K PNG images via hyperfine. Full numbers in the root BENCHMARKS.md.

Tool4k/14k/24k/3vs blazediff
blazediff~275ms~342ms~347ms-
blazediff (encoded buffer input)~203ms~256ms~270ms-
odiff~1266ms~1538ms~1799ms4.5-5.2x slower

Binary sizes (stripped, LTO optimized) - ~3x smaller than odiff:

Platformblazediffodiff
macOS ARM64702 KB2.2 MB
macOS x64773 KB2.6 MB
Linux ARM64753 KB2.3 MB
Linux x64869 KB2.9 MB
Windows ARM64580 KB2.4 MB
Windows x64915 KB3.0 MB

Algorithm

BlazeDiff uses a two-pass block-based approach with SIMD acceleration:

  1. Cold Pass: Scans 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: Uses NEON (ARM) or SSE4.1 (x86) for parallel pixel processing
  4. Anti-aliasing: Implements Vysniauskas (2009) algorithm to detect AA artifacts

References

  • YIQ Color Space: Kotsarenko & Ramos (2009) - "Measuring perceived color difference using YIQ NTSC transmission color space"
  • Anti-Aliasing Detection: Vysniauskas (2009) - "Anti-aliased Pixel and Intensity Slope Detector"
  • Inspiration: odiff - Fast image comparison tool written in Zig

版本与发布记录

@blazediff/core-native 共发布 17 个版本,首次发布于 2026/03/12;过去 12 个月发布了 17 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
7.0.0latest2026/11/053 天前
6.0.22026/10/2612 天前
6.0.12026/08/272 个月前
6.0.02026/08/172 个月前
5.4.02026/08/033 个月前
5.3.02026/07/163 个月前

关于 @blazediff/core-native 的常见问题

@blazediff/core-native 是什么?

Native Rust binaries for blazediff - the fastest image diff in the world

如何安装 @blazediff/core-native?

在项目目录运行 npm install @blazediff/core-native,或使用 pnpm add / yarn add / bun add。

@blazediff/core-native 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@blazediff/core-native 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@blazediff/core-native 可以商用吗?

@blazediff/core-native 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@blazediff/core-native 的下载量有多少?

根据 npm 官方下载统计,@blazediff/core-native 在 2026/10/09 – 2026/11/07 这 30 天内被下载 19,974 次,日均约 666 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@blazediff/core-native 还在维护吗?

最新版本 7.0.0 发布于 2026/11/05(3 天前);至今共发布 17 个版本,其中过去 12 个月发布了 17 个;首次发布于 2026/03/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。