@blazediff/bin 1.7.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,118 +7,203 @@
7
7
 
8
8
  </div>
9
9
 
10
- Command-line interface for the BlazeDiff image comparison library.
10
+ The fastest single-threaded image diff in the world. Native Rust implementation with SIMD optimization, **3-4x faster** and **3x smaller** than [odiff](https://github.com/dmtrKovalenko/odiff).
11
+
12
+ **Features:**
13
+ - SIMD-accelerated (NEON on ARM, SSE4.1 on x86)
14
+ - Block-based two-pass optimization
15
+ - YIQ perceptual color difference
16
+ - Anti-aliasing detection
17
+ - Cross-platform pre-built binaries (~700KB-900KB, no compilation required)
11
18
 
12
19
  ## Installation
13
20
 
14
21
  ```bash
15
- npm install -g @blazediff/bin
22
+ npm install @blazediff/bin
16
23
  ```
17
24
 
18
- ## Usage
19
-
20
- ```bash
21
- blazediff <command> <image1> <image2> [options]
25
+ Pre-built [binaries](https://github.com/teimurjan/blazediff/tree/main/packages/bin/binaries) are included for:
26
+ - macOS ARM64 (Apple Silicon)
27
+ - macOS x64 (Intel)
28
+ - Linux ARM64
29
+ - Linux x64
30
+ - Windows ARM64
31
+ - Windows x64
32
+
33
+ ## API
34
+
35
+ ### compare(basePath, comparePath, diffOutput, options?)
36
+
37
+ Compare two PNG images and generate a diff image.
38
+
39
+ <table>
40
+ <tr>
41
+ <th width="500">Parameter</th>
42
+ <th width="500">Type</th>
43
+ <th width="500">Description</th>
44
+ </tr>
45
+ <tr>
46
+ <td><code>basePath</code></td>
47
+ <td>string</td>
48
+ <td>Path to the base/expected image</td>
49
+ </tr>
50
+ <tr>
51
+ <td><code>comparePath</code></td>
52
+ <td>string</td>
53
+ <td>Path to the comparison/actual image</td>
54
+ </tr>
55
+ <tr>
56
+ <td><code>diffOutput</code></td>
57
+ <td>string</td>
58
+ <td>Path where the diff image will be saved</td>
59
+ </tr>
60
+ <tr>
61
+ <td><code>options</code></td>
62
+ <td>BlazeDiffOptions</td>
63
+ <td>Comparison options (optional)</td>
64
+ </tr>
65
+ </table>
66
+
67
+ <strong>Returns:</strong> `Promise<BlazeDiffResult>`
68
+
69
+ <table>
70
+ <tr>
71
+ <th width="500">Option</th>
72
+ <th width="500">Type</th>
73
+ <th width="500">Default</th>
74
+ <th width="500">Description</th>
75
+ </tr>
76
+ <tr>
77
+ <td><code>threshold</code></td>
78
+ <td>number</td>
79
+ <td>0.1</td>
80
+ <td>Color difference threshold (0.0-1.0). Lower = more strict</td>
81
+ </tr>
82
+ <tr>
83
+ <td><code>antialiasing</code></td>
84
+ <td>boolean</td>
85
+ <td>false</td>
86
+ <td>Enable anti-aliasing detection to exclude AA pixels from diff count</td>
87
+ </tr>
88
+ <tr>
89
+ <td><code>diffMask</code></td>
90
+ <td>boolean</td>
91
+ <td>false</td>
92
+ <td>Output only differences with transparent background</td>
93
+ </tr>
94
+ <tr>
95
+ <td><code>failOnLayoutDiff</code></td>
96
+ <td>boolean</td>
97
+ <td>false</td>
98
+ <td>Fail immediately if images have different dimensions</td>
99
+ </tr>
100
+ </table>
101
+
102
+ ### Result Types
103
+
104
+ ```typescript
105
+ type BlazeDiffResult =
106
+ | { match: true }
107
+ | { match: false; reason: "layout-diff" }
108
+ | { match: false; reason: "pixel-diff"; diffCount: number; diffPercentage: number }
109
+ | { match: false; reason: "file-not-exists"; file: string };
22
110
  ```
23
111
 
24
- ## Commands
112
+ ## Usage
25
113
 
26
- BlazeDiff supports multiple comparison algorithms, each optimized for different use cases:
114
+ ### Programmatic API
27
115
 
28
- ### `diff` - Pixel-by-pixel comparison (default)
29
- Fast pixel-level comparison for detecting visual regressions.
116
+ ```typescript
117
+ import { compare } from '@blazediff/bin';
30
118
 
31
- ```bash
32
- blazediff diff image1.png image2.png [options]
33
- # Or simply:
34
- blazediff image1.png image2.png [options]
119
+ const result = await compare('expected.png', 'actual.png', 'diff.png', {
120
+ threshold: 0.1,
121
+ antialiasing: true,
122
+ });
123
+
124
+ if (result.match) {
125
+ console.log('Images are identical!');
126
+ } else if (result.reason === 'pixel-diff') {
127
+ console.log(`${result.diffCount} pixels differ (${result.diffPercentage.toFixed(2)}%)`);
128
+ } else if (result.reason === 'layout-diff') {
129
+ console.log('Images have different dimensions');
130
+ }
35
131
  ```
36
132
 
37
- **Options:**
38
- - `-o, --output <path>` - Output path for the diff image
39
- - `-t, --threshold <num>` - Matching threshold (0 to 1, default: 0.1)
40
- - `-a, --alpha <num>` - Opacity of original image in diff (default: 0.1)
41
- - `--aa-color <r,g,b>` - Color for anti-aliased pixels (default: 255,255,0)
42
- - `--diff-color <r,g,b>` - Color for different pixels (default: 255,0,0)
43
- - `--diff-color-alt <r,g,b>` - Alternative color for dark differences
44
- - `--include-aa` - Include anti-aliasing detection
45
- - `--diff-mask` - Draw diff over transparent background
46
- - `--color-space <name>` - Specify color space to use (yiq, ycbcr)
47
- - `--transformer <name>` - Specify transformer to use (pngjs, sharp)
48
- - `-h, --help` - Show help message
49
-
50
- ### `gmsd` - Gradient Magnitude Similarity Deviation
51
- Perceptual quality metric based on gradient similarity.
133
+ ### CLI Usage
52
134
 
53
135
  ```bash
54
- blazediff gmsd image1.png image2.png [options]
55
- ```
136
+ # Compare two images
137
+ npx blazediff expected.png actual.png diff.png
56
138
 
57
- **Options:**
58
- - `-o, --output <path>` - Output path for GMS similarity map
59
- - `--downsample <0|1>` - Downsample factor (0=full-res, 1=2x, default: 0)
60
- - `--gmsd-c <num>` - Stability constant (default: 170)
61
- - `--transformer <name>` - Specify transformer to use (pngjs, sharp)
62
- - `-h, --help` - Show help message
139
+ # With options
140
+ npx blazediff expected.png actual.png diff.png --threshold 0.05 --antialiasing
63
141
 
64
- ### `ssim` - Structural Similarity Index
65
- Industry-standard metric for measuring structural similarity.
142
+ # With higher compression (smaller output file, slower)
143
+ npx blazediff expected.png actual.png diff.png -c 6
66
144
 
67
- ```bash
68
- blazediff ssim image1.png image2.png [options]
145
+ # Output as JSON
146
+ npx blazediff expected.png actual.png diff.png --output-format json
69
147
  ```
70
148
 
71
- **Options:**
72
- - `-o, --output <path>` - Output path for SSIM map visualization
73
- - `--transformer <name>` - Specify transformer to use (pngjs, sharp)
74
- - `-h, --help` - Show help message
75
-
76
- ### `msssim` - Multi-Scale Structural Similarity Index
77
- Enhanced SSIM that operates at multiple image scales.
149
+ ### CLI Options
78
150
 
79
- ```bash
80
- blazediff msssim image1.png image2.png [options]
151
+ ```
152
+ Usage: blazediff [OPTIONS] <IMAGE1> <IMAGE2> <OUTPUT>
153
+
154
+ Arguments:
155
+ <IMAGE1> First image path
156
+ <IMAGE2> Second image path
157
+ <OUTPUT> Output diff image path
158
+
159
+ Options:
160
+ -t, --threshold <THRESHOLD> Color difference threshold (0.0-1.0) [default: 0.1]
161
+ -a, --antialiasing Enable anti-aliasing detection
162
+ --diff-mask Output only differences (transparent background)
163
+ --fail-on-layout Fail on layout (size) difference
164
+ -c, --compression <LEVEL> PNG compression level (0-9, 0=fastest/largest, 9=slowest/smallest) [default: 0]
165
+ --output-format <FORMAT> Output format (json or text) [default: json]
166
+ -h, --help Print help
167
+ -V, --version Print version
81
168
  ```
82
169
 
83
- **Options:**
84
- - `-o, --output <path>` - Output path for MS-SSIM map visualization
85
- - `--transformer <name>` - Specify transformer to use (pngjs, sharp)
86
- - `-h, --help` - Show help message
170
+ ### Exit Codes
87
171
 
88
- ## Examples
172
+ - `0` - Images are identical
173
+ - `1` - Images differ (or layout mismatch with `--fail-on-layout`)
174
+ - `2` - Error (file not found, invalid format, etc.)
89
175
 
90
- ```bash
91
- # Pixel-by-pixel diff (default)
92
- blazediff image1.png image2.png
93
- blazediff diff image1.png image2.png -o diff.png -t 0.05
176
+ ## Performance
94
177
 
95
- # GMSD similarity metric
96
- blazediff gmsd image1.png image2.png
97
- blazediff gmsd image1.png image2.png -o gms-map.png
178
+ Benchmarked on Apple M1 Pro with 5600x3200 4K images:
98
179
 
99
- # SSIM structural similarity
100
- blazediff ssim image1.png image2.png
101
- blazediff ssim image1.png image2.png -o ssim-map.png
180
+ | Tool | Benchmark Time | vs blazediff |
181
+ |------|------|--------------|
182
+ | **blazediff** | ~327ms | - |
183
+ | odiff | ~1215ms | 3.4x slower |
102
184
 
103
- # MS-SSIM multi-scale similarity
104
- blazediff msssim image1.png image2.png
105
- blazediff msssim image1.png image2.png -o msssim-map.png
185
+ Binary sizes (stripped, LTO optimized) - **~3x smaller than odiff**:
106
186
 
107
- # Use Sharp transformer for better performance
108
- blazediff ssim image1.jpg image2.jpg --transformer sharp
109
- ```
187
+ | Platform | blazediff | odiff |
188
+ |----------|-----------|-------|
189
+ | macOS ARM64 | 702 KB | 2.2 MB |
190
+ | macOS x64 | 773 KB | 2.6 MB |
191
+ | Linux ARM64 | 753 KB | 2.3 MB |
192
+ | Linux x64 | 869 KB | 2.9 MB |
193
+ | Windows ARM64 | 580 KB | 2.4 MB |
194
+ | Windows x64 | 915 KB | 3.0 MB |
110
195
 
111
- ## Transformers
196
+ ## Algorithm
112
197
 
113
- - **pngjs** - Pure JavaScript, works everywhere. Supports PNG only.
114
- - **sharp** - Native bindings, significantly faster. Supports PNG and JPEG.
198
+ BlazeDiff uses a two-pass block-based approach with SIMD acceleration:
115
199
 
116
- ## Exit Codes
200
+ 1. **Cold Pass**: Scans image in 8x8 blocks using 32-bit integer comparison to identify changed regions
201
+ 2. **Hot Pass**: Only processes blocks marked as changed, applying YIQ perceptual color difference
202
+ 3. **SIMD**: Uses NEON (ARM) or SSE4.1 (x86) for parallel pixel processing
203
+ 4. **Anti-aliasing**: Implements Vysniauskas (2009) algorithm to detect AA artifacts
117
204
 
118
- ### Diff Mode
119
- - `0` - Images are identical
120
- - `1` - Images have differences or error occurred
205
+ ## References
121
206
 
122
- ### GMSD, SSIM, MS-SSIM Modes
123
- - `0` - Images are highly similar (score >= 0.95)
124
- - `1` - Images have noticeable differences (score < 0.95) or error occurred
207
+ - **YIQ Color Space**: [Kotsarenko & Ramos (2009)](https://doaj.org/article/b2e3b5088ba943eebd9af2927fef08ad) - "Measuring perceived color difference using YIQ NTSC transmission color space"
208
+ - **Anti-Aliasing Detection**: [Vysniauskas (2009)](https://www.researchgate.net/publication/234073157_Anti-aliased_Pixel_and_Intensity_Slope_Detector) - "Anti-aliased Pixel and Intensity Slope Detector"
209
+ - **Inspiration**: [odiff](https://github.com/dmtrKovalenko/odiff) - Fast image comparison tool written in Zig
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/index.d.mts CHANGED
@@ -1,69 +1,46 @@
1
- interface Image {
2
- data: Buffer | Uint8Array | Uint8ClampedArray;
3
- width: number;
4
- height: number;
5
- }
6
- interface Transformer {
7
- read: (input: string | Buffer) => Promise<Image>;
8
- write: (image: Image, output: string | Buffer) => Promise<void>;
9
- }
10
- type ComparisonMode = "diff" | "gmsd" | "ssim" | "msssim";
11
- interface DiffModeOptions {
12
- outputPath?: string;
13
- transformer: Transformer;
14
- mode?: "diff";
15
- options?: Record<string, unknown>;
16
- }
17
- interface GmsdModeOptions {
18
- outputPath?: string;
19
- transformer: Transformer;
20
- mode: "gmsd";
21
- options?: Record<string, unknown>;
22
- }
23
- interface SsimModeOptions {
24
- outputPath?: string;
25
- transformer: Transformer;
26
- mode: "ssim";
27
- options?: Record<string, unknown>;
28
- }
29
- interface MsssimModeOptions {
30
- outputPath?: string;
31
- transformer: Transformer;
32
- mode: "msssim";
33
- options?: Record<string, unknown>;
34
- }
35
- interface DiffModeResult {
36
- mode: "diff";
1
+ interface BlazeDiffOptions {
2
+ /** Color difference threshold (0.0-1.0). Lower = more strict. Default: 0.1 */
3
+ threshold?: number;
4
+ /** Enable anti-aliasing detection to exclude AA pixels from diff count */
5
+ antialiasing?: boolean;
6
+ /** Output only differences with transparent background */
7
+ diffMask?: boolean;
8
+ /** Fail immediately if images have different dimensions */
9
+ failOnLayoutDiff?: boolean;
10
+ /** PNG compression level (0-9, 0=fastest/largest, 9=slowest/smallest) */
11
+ compression?: number;
12
+ }
13
+ type BlazeDiffResult = {
14
+ match: true;
15
+ } | {
16
+ match: false;
17
+ reason: "layout-diff";
18
+ } | {
19
+ match: false;
20
+ reason: "pixel-diff";
37
21
  diffCount: number;
38
- width: number;
39
- height: number;
40
- outputData?: Uint8Array;
41
- duration: number;
42
- }
43
- interface GmsdModeResult {
44
- mode: "gmsd";
45
- score: number;
46
- width: number;
47
- height: number;
48
- outputData?: Uint8Array;
49
- duration: number;
50
- }
51
- interface SsimModeResult {
52
- mode: "ssim";
53
- score: number;
54
- width: number;
55
- height: number;
56
- outputData?: Uint8Array;
57
- duration: number;
58
- }
59
- interface MsssimModeResult {
60
- mode: "msssim";
61
- score: number;
62
- width: number;
63
- height: number;
64
- outputData?: Uint8Array;
65
- duration: number;
66
- }
67
- type BlazeDiffBinResult = DiffModeResult | GmsdModeResult | SsimModeResult | MsssimModeResult;
22
+ diffPercentage: number;
23
+ } | {
24
+ match: false;
25
+ reason: "file-not-exists";
26
+ file: string;
27
+ };
28
+ /**
29
+ * Compare two PNG images and generate a diff image.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const result = await compare('expected.png', 'actual.png', 'diff.png');
34
+ *
35
+ * if (result.match) {
36
+ * console.log('Images identical');
37
+ * } else if (result.reason === 'pixel-diff') {
38
+ * console.log(`${result.diffCount} pixels differ`);
39
+ * }
40
+ * ```
41
+ */
42
+ declare function compare(basePath: string, comparePath: string, diffOutput: string, options?: BlazeDiffOptions): Promise<BlazeDiffResult>;
43
+ /** Get the path to the blazediff binary for direct CLI usage. */
44
+ declare function getBinaryPath(): string;
68
45
 
69
- export type { BlazeDiffBinResult, ComparisonMode, DiffModeOptions, DiffModeResult, GmsdModeOptions, GmsdModeResult, Image, MsssimModeOptions, MsssimModeResult, SsimModeOptions, SsimModeResult, Transformer };
46
+ export { type BlazeDiffOptions, type BlazeDiffResult, compare, getBinaryPath };
package/dist/index.d.ts CHANGED
@@ -1,69 +1,46 @@
1
- interface Image {
2
- data: Buffer | Uint8Array | Uint8ClampedArray;
3
- width: number;
4
- height: number;
5
- }
6
- interface Transformer {
7
- read: (input: string | Buffer) => Promise<Image>;
8
- write: (image: Image, output: string | Buffer) => Promise<void>;
9
- }
10
- type ComparisonMode = "diff" | "gmsd" | "ssim" | "msssim";
11
- interface DiffModeOptions {
12
- outputPath?: string;
13
- transformer: Transformer;
14
- mode?: "diff";
15
- options?: Record<string, unknown>;
16
- }
17
- interface GmsdModeOptions {
18
- outputPath?: string;
19
- transformer: Transformer;
20
- mode: "gmsd";
21
- options?: Record<string, unknown>;
22
- }
23
- interface SsimModeOptions {
24
- outputPath?: string;
25
- transformer: Transformer;
26
- mode: "ssim";
27
- options?: Record<string, unknown>;
28
- }
29
- interface MsssimModeOptions {
30
- outputPath?: string;
31
- transformer: Transformer;
32
- mode: "msssim";
33
- options?: Record<string, unknown>;
34
- }
35
- interface DiffModeResult {
36
- mode: "diff";
1
+ interface BlazeDiffOptions {
2
+ /** Color difference threshold (0.0-1.0). Lower = more strict. Default: 0.1 */
3
+ threshold?: number;
4
+ /** Enable anti-aliasing detection to exclude AA pixels from diff count */
5
+ antialiasing?: boolean;
6
+ /** Output only differences with transparent background */
7
+ diffMask?: boolean;
8
+ /** Fail immediately if images have different dimensions */
9
+ failOnLayoutDiff?: boolean;
10
+ /** PNG compression level (0-9, 0=fastest/largest, 9=slowest/smallest) */
11
+ compression?: number;
12
+ }
13
+ type BlazeDiffResult = {
14
+ match: true;
15
+ } | {
16
+ match: false;
17
+ reason: "layout-diff";
18
+ } | {
19
+ match: false;
20
+ reason: "pixel-diff";
37
21
  diffCount: number;
38
- width: number;
39
- height: number;
40
- outputData?: Uint8Array;
41
- duration: number;
42
- }
43
- interface GmsdModeResult {
44
- mode: "gmsd";
45
- score: number;
46
- width: number;
47
- height: number;
48
- outputData?: Uint8Array;
49
- duration: number;
50
- }
51
- interface SsimModeResult {
52
- mode: "ssim";
53
- score: number;
54
- width: number;
55
- height: number;
56
- outputData?: Uint8Array;
57
- duration: number;
58
- }
59
- interface MsssimModeResult {
60
- mode: "msssim";
61
- score: number;
62
- width: number;
63
- height: number;
64
- outputData?: Uint8Array;
65
- duration: number;
66
- }
67
- type BlazeDiffBinResult = DiffModeResult | GmsdModeResult | SsimModeResult | MsssimModeResult;
22
+ diffPercentage: number;
23
+ } | {
24
+ match: false;
25
+ reason: "file-not-exists";
26
+ file: string;
27
+ };
28
+ /**
29
+ * Compare two PNG images and generate a diff image.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const result = await compare('expected.png', 'actual.png', 'diff.png');
34
+ *
35
+ * if (result.match) {
36
+ * console.log('Images identical');
37
+ * } else if (result.reason === 'pixel-diff') {
38
+ * console.log(`${result.diffCount} pixels differ`);
39
+ * }
40
+ * ```
41
+ */
42
+ declare function compare(basePath: string, comparePath: string, diffOutput: string, options?: BlazeDiffOptions): Promise<BlazeDiffResult>;
43
+ /** Get the path to the blazediff binary for direct CLI usage. */
44
+ declare function getBinaryPath(): string;
68
45
 
69
- export type { BlazeDiffBinResult, ComparisonMode, DiffModeOptions, DiffModeResult, GmsdModeOptions, GmsdModeResult, Image, MsssimModeOptions, MsssimModeResult, SsimModeOptions, SsimModeResult, Transformer };
46
+ export { type BlazeDiffOptions, type BlazeDiffResult, compare, getBinaryPath };
package/dist/index.js CHANGED
@@ -1 +1,108 @@
1
- 'use strict';
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ compare: () => compare,
34
+ getBinaryPath: () => getBinaryPath
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_node_child_process = require("child_process");
38
+ var import_node_path = __toESM(require("path"));
39
+ var import_node_util = require("util");
40
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
41
+ var BINARY_PATH = import_node_path.default.join(__dirname, "..", "bin", "blazediff.exe");
42
+ function buildArgs(diffOutput, options) {
43
+ const args = [diffOutput, "--output-format=json"];
44
+ if (!options) return args;
45
+ if (options.threshold !== void 0) args.push(`--threshold=${options.threshold}`);
46
+ if (options.antialiasing) args.push("--antialiasing");
47
+ if (options.diffMask) args.push("--diff-mask");
48
+ if (options.failOnLayoutDiff) args.push("--fail-on-layout");
49
+ if (options.compression !== void 0) args.push(`--compression=${options.compression}`);
50
+ return args;
51
+ }
52
+ function parseJsonOutput(text) {
53
+ try {
54
+ return JSON.parse(text);
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+ function detectMissingFile(error, basePath, comparePath) {
60
+ if (!/Failed to load images:.*(?:No such file|not found)/i.test(error)) {
61
+ return null;
62
+ }
63
+ if (error.includes(basePath)) return basePath;
64
+ if (error.includes(comparePath)) return comparePath;
65
+ return basePath;
66
+ }
67
+ async function compare(basePath, comparePath, diffOutput, options) {
68
+ const args = [basePath, comparePath, ...buildArgs(diffOutput, options)];
69
+ try {
70
+ await execFileAsync(BINARY_PATH, args);
71
+ return { match: true };
72
+ } catch (err) {
73
+ const { code, stdout, stderr } = err;
74
+ const output = stdout || stderr || "";
75
+ if (code === 1) {
76
+ const json = parseJsonOutput(output);
77
+ if (json?.error?.includes("Layout differs")) {
78
+ return { match: false, reason: "layout-diff" };
79
+ }
80
+ if (json) {
81
+ return {
82
+ match: false,
83
+ reason: "pixel-diff",
84
+ diffCount: json.diffCount,
85
+ diffPercentage: json.diffPercentage
86
+ };
87
+ }
88
+ if (output.includes("Layout differs")) {
89
+ return { match: false, reason: "layout-diff" };
90
+ }
91
+ }
92
+ if (code === 2) {
93
+ const missingFile = detectMissingFile(output, basePath, comparePath);
94
+ if (missingFile) {
95
+ return { match: false, reason: "file-not-exists", file: missingFile };
96
+ }
97
+ }
98
+ throw new Error(output || `blazediff exited with code ${code}`);
99
+ }
100
+ }
101
+ function getBinaryPath() {
102
+ return BINARY_PATH;
103
+ }
104
+ // Annotate the CommonJS export names for ESM import in node:
105
+ 0 && (module.exports = {
106
+ compare,
107
+ getBinaryPath
108
+ });