@blazediff/bin 1.4.1 → 1.5.0
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/dist/cli.js +149 -30
- package/dist/index.d.mts +36 -7
- package/dist/index.d.ts +36 -7
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/index.ts
|
|
27
27
|
var import_core = __toESM(require("@blazediff/core"));
|
|
28
|
-
|
|
28
|
+
var import_gmsd = __toESM(require("@blazediff/gmsd"));
|
|
29
|
+
var isGmsdModeOptions = (options) => {
|
|
30
|
+
return options.mode === "gmsd";
|
|
31
|
+
};
|
|
32
|
+
async function bin(image1Path, image2Path, options) {
|
|
29
33
|
const [image1, image2] = await Promise.all([
|
|
30
34
|
options.transformer.transform(image1Path),
|
|
31
35
|
options.transformer.transform(image2Path)
|
|
@@ -35,6 +39,40 @@ async function blazeDiffBin(image1Path, image2Path, options) {
|
|
|
35
39
|
`Image dimensions do not match: ${image1.width}x${image1.height} vs ${image2.width}x${image2.height}`
|
|
36
40
|
);
|
|
37
41
|
}
|
|
42
|
+
if (isGmsdModeOptions(options)) {
|
|
43
|
+
let outputData2;
|
|
44
|
+
if (options.outputPath) {
|
|
45
|
+
outputData2 = new Uint8Array(image1.data.length);
|
|
46
|
+
}
|
|
47
|
+
const startTime2 = performance.now();
|
|
48
|
+
const score = (0, import_gmsd.default)(
|
|
49
|
+
image1.data,
|
|
50
|
+
image2.data,
|
|
51
|
+
outputData2,
|
|
52
|
+
image1.width,
|
|
53
|
+
image1.height,
|
|
54
|
+
options.options || {}
|
|
55
|
+
);
|
|
56
|
+
const duration2 = performance.now() - startTime2;
|
|
57
|
+
if (options.outputPath && outputData2) {
|
|
58
|
+
await options.transformer.write(
|
|
59
|
+
{
|
|
60
|
+
data: outputData2,
|
|
61
|
+
width: image1.width,
|
|
62
|
+
height: image1.height
|
|
63
|
+
},
|
|
64
|
+
options.outputPath
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
mode: "gmsd",
|
|
69
|
+
width: image1.width,
|
|
70
|
+
height: image1.height,
|
|
71
|
+
outputData: outputData2,
|
|
72
|
+
duration: duration2,
|
|
73
|
+
score
|
|
74
|
+
};
|
|
75
|
+
}
|
|
38
76
|
let outputData;
|
|
39
77
|
if (options.outputPath) {
|
|
40
78
|
outputData = new Uint8Array(image1.data.length);
|
|
@@ -46,7 +84,7 @@ async function blazeDiffBin(image1Path, image2Path, options) {
|
|
|
46
84
|
outputData,
|
|
47
85
|
image1.width,
|
|
48
86
|
image1.height,
|
|
49
|
-
options.
|
|
87
|
+
options.options || {}
|
|
50
88
|
);
|
|
51
89
|
const duration = performance.now() - startTime;
|
|
52
90
|
if (diffCount > 0 && options.outputPath && outputData) {
|
|
@@ -60,6 +98,7 @@ async function blazeDiffBin(image1Path, image2Path, options) {
|
|
|
60
98
|
);
|
|
61
99
|
}
|
|
62
100
|
return {
|
|
101
|
+
mode: "diff",
|
|
63
102
|
diffCount,
|
|
64
103
|
width: image1.width,
|
|
65
104
|
height: image1.height,
|
|
@@ -77,7 +116,12 @@ Arguments:
|
|
|
77
116
|
image1 Path to the first image
|
|
78
117
|
image2 Path to the second image
|
|
79
118
|
|
|
80
|
-
Options:
|
|
119
|
+
General Options:
|
|
120
|
+
-m, --mode <mode> Comparison mode: "diff" or "gmsd" (default: diff)
|
|
121
|
+
--transformer <name> Specify transformer to use (e.g. pngjs, sharp)
|
|
122
|
+
-h, --help Show this help message
|
|
123
|
+
|
|
124
|
+
Diff Mode Options (default mode):
|
|
81
125
|
-o, --output <path> Output path for the diff image
|
|
82
126
|
-t, --threshold <num> Matching threshold (0 to 1, default: 0.1)
|
|
83
127
|
-a, --alpha <num> Opacity of original image in diff (default: 0.1)
|
|
@@ -86,14 +130,23 @@ Options:
|
|
|
86
130
|
--diff-color-alt <r,g,b> Alternative color for dark differences (default: same as diff-color)
|
|
87
131
|
--include-aa Include anti-aliasing detection
|
|
88
132
|
--diff-mask Draw diff over transparent background
|
|
89
|
-
--transformer <name> Specify transformer to use (e.g. pngjs, sharp)
|
|
90
133
|
--color-space <name> Specify color space to use (e.g. yiq, ycbcr)
|
|
91
|
-
|
|
134
|
+
|
|
135
|
+
GMSD Mode Options (--mode gmsd):
|
|
136
|
+
-o, --output <path> Output path for GMS similarity map (grayscale visualization)
|
|
137
|
+
--downsample <0|1> Downsample factor: 0=full-res, 1=2x downsample (default: 0)
|
|
138
|
+
--gmsd-c <num> Stability constant for GMSD (default: 170)
|
|
92
139
|
|
|
93
140
|
Examples:
|
|
141
|
+
# Pixel-by-pixel diff (default)
|
|
94
142
|
blazediff image1.png image2.png
|
|
95
143
|
blazediff image1.png image2.png -o diff.png -t 0.05
|
|
96
144
|
blazediff image1.png image2.png --threshold 0.2 --alpha 0.3
|
|
145
|
+
|
|
146
|
+
# GMSD similarity score
|
|
147
|
+
blazediff image1.png image2.png --mode gmsd
|
|
148
|
+
blazediff image1.png image2.png --mode gmsd --downsample 1
|
|
149
|
+
blazediff image1.png image2.png --mode gmsd -o gms-map.png
|
|
97
150
|
`);
|
|
98
151
|
}
|
|
99
152
|
function parseRGB(colorStr) {
|
|
@@ -192,6 +245,40 @@ function parseArgs() {
|
|
|
192
245
|
i++;
|
|
193
246
|
}
|
|
194
247
|
break;
|
|
248
|
+
case "-m":
|
|
249
|
+
case "--mode":
|
|
250
|
+
if (nextArg) {
|
|
251
|
+
if (nextArg !== "diff" && nextArg !== "gmsd") {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`Invalid mode: ${nextArg}. Must be "diff" or "gmsd"`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
options.mode = nextArg;
|
|
257
|
+
i++;
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
case "--downsample":
|
|
261
|
+
if (nextArg) {
|
|
262
|
+
const downsample = parseInt(nextArg, 10);
|
|
263
|
+
if (downsample !== 0 && downsample !== 1) {
|
|
264
|
+
throw new Error(`Invalid downsample: ${nextArg}. Must be 0 or 1`);
|
|
265
|
+
}
|
|
266
|
+
options.downsample = downsample;
|
|
267
|
+
i++;
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
case "--gmsd-c":
|
|
271
|
+
if (nextArg) {
|
|
272
|
+
const gmsdC = parseFloat(nextArg);
|
|
273
|
+
if (Number.isNaN(gmsdC) || gmsdC <= 0) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Invalid gmsd-c: ${nextArg}. Must be a positive number`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
options.gmsdC = gmsdC;
|
|
279
|
+
i++;
|
|
280
|
+
}
|
|
281
|
+
break;
|
|
195
282
|
default:
|
|
196
283
|
console.error(`Unknown option: ${arg}`);
|
|
197
284
|
printUsage();
|
|
@@ -215,33 +302,65 @@ async function main() {
|
|
|
215
302
|
try {
|
|
216
303
|
const { image1, image2, options } = parseArgs();
|
|
217
304
|
const transformer = await getTransformer(options.transformer);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
305
|
+
let result;
|
|
306
|
+
if (options.mode === "gmsd") {
|
|
307
|
+
const binOptions = {
|
|
308
|
+
outputPath: options.outputPath,
|
|
309
|
+
transformer,
|
|
310
|
+
mode: "gmsd",
|
|
311
|
+
options: {
|
|
312
|
+
downsample: options.downsample || 0,
|
|
313
|
+
c: options.gmsdC
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
result = await bin(image1, image2, binOptions);
|
|
317
|
+
} else {
|
|
318
|
+
const binOptions = {
|
|
319
|
+
outputPath: options.outputPath,
|
|
320
|
+
transformer,
|
|
321
|
+
mode: "diff",
|
|
322
|
+
options: {
|
|
323
|
+
threshold: options.threshold,
|
|
324
|
+
alpha: options.alpha,
|
|
325
|
+
aaColor: options.aaColor,
|
|
326
|
+
diffColor: options.diffColor,
|
|
327
|
+
diffColorAlt: options.diffColorAlt,
|
|
328
|
+
includeAA: options.includeAA,
|
|
329
|
+
diffMask: options.diffMask
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
result = await bin(image1, image2, binOptions);
|
|
239
333
|
}
|
|
240
|
-
|
|
241
|
-
|
|
334
|
+
console.log(`completed in: ${result.duration.toFixed(2)}ms`);
|
|
335
|
+
console.log(`dimensions: ${result.width}x${result.height}`);
|
|
336
|
+
if (result.mode === "gmsd") {
|
|
337
|
+
console.log(
|
|
338
|
+
`similarity score: ${result.score.toFixed(6)} (0=different, 1=identical)`
|
|
339
|
+
);
|
|
340
|
+
console.log(`similarity: ${(result.score * 100).toFixed(2)}%`);
|
|
341
|
+
if (options.outputPath && result.outputData) {
|
|
342
|
+
console.log(`GMS map saved to: ${options.outputPath}`);
|
|
343
|
+
}
|
|
344
|
+
if (result.score < 0.95) {
|
|
345
|
+
process.exit(1);
|
|
346
|
+
} else {
|
|
347
|
+
console.log(`Images are highly similar!`);
|
|
348
|
+
process.exit(0);
|
|
349
|
+
}
|
|
242
350
|
} else {
|
|
243
|
-
console.log(`
|
|
244
|
-
|
|
351
|
+
console.log(`different pixels: ${result.diffCount}`);
|
|
352
|
+
console.log(
|
|
353
|
+
`error: ${(result.diffCount / (result.width * result.height) * 100).toFixed(2)}%`
|
|
354
|
+
);
|
|
355
|
+
if (result.diffCount > 0 && result.outputData && options.outputPath) {
|
|
356
|
+
console.log(`diff image: ${options.outputPath}`);
|
|
357
|
+
}
|
|
358
|
+
if (result.diffCount > 0) {
|
|
359
|
+
process.exit(1);
|
|
360
|
+
} else {
|
|
361
|
+
console.log(`Images are identical!`);
|
|
362
|
+
process.exit(0);
|
|
363
|
+
}
|
|
245
364
|
}
|
|
246
365
|
} catch (error) {
|
|
247
366
|
console.error(
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CoreOptions } from '@blazediff/core';
|
|
2
|
+
import { GmsdOptions } from '@blazediff/gmsd';
|
|
2
3
|
|
|
3
|
-
interface
|
|
4
|
+
interface Image {
|
|
5
|
+
data: Buffer | Uint8Array | Uint8ClampedArray;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
interface Transformer {
|
|
10
|
+
transform: (input: string | Buffer) => Promise<Image>;
|
|
11
|
+
write: (image: Image, output: string | Buffer) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
type ComparisonMode = "diff" | "gmsd";
|
|
14
|
+
interface DiffModeOptions {
|
|
15
|
+
outputPath?: string;
|
|
16
|
+
transformer: Transformer;
|
|
17
|
+
mode?: "diff";
|
|
18
|
+
options?: CoreOptions;
|
|
19
|
+
}
|
|
20
|
+
interface GmsdModeOptions {
|
|
4
21
|
outputPath?: string;
|
|
5
|
-
transformer:
|
|
6
|
-
|
|
22
|
+
transformer: Transformer;
|
|
23
|
+
mode: "gmsd";
|
|
24
|
+
options?: GmsdOptions;
|
|
7
25
|
}
|
|
8
|
-
interface
|
|
26
|
+
interface DiffModeResult {
|
|
27
|
+
mode: "diff";
|
|
9
28
|
diffCount: number;
|
|
10
29
|
width: number;
|
|
11
30
|
height: number;
|
|
12
31
|
outputData?: Uint8Array;
|
|
13
32
|
duration: number;
|
|
14
33
|
}
|
|
15
|
-
|
|
34
|
+
interface GmsdModeResult {
|
|
35
|
+
mode: "gmsd";
|
|
36
|
+
score: number;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
outputData?: Uint8Array;
|
|
40
|
+
duration: number;
|
|
41
|
+
}
|
|
42
|
+
type BlazeDiffBinResult = DiffModeResult | GmsdModeResult;
|
|
43
|
+
declare function bin(image1Path: string, image2Path: string, options: GmsdModeOptions): Promise<GmsdModeResult>;
|
|
44
|
+
declare function bin(image1Path: string, image2Path: string, options: DiffModeOptions): Promise<DiffModeResult>;
|
|
16
45
|
|
|
17
|
-
export { type
|
|
46
|
+
export { type BlazeDiffBinResult, type ComparisonMode, type DiffModeOptions, type DiffModeResult, type GmsdModeOptions, type GmsdModeResult, type Image, type Transformer, bin as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CoreOptions } from '@blazediff/core';
|
|
2
|
+
import { GmsdOptions } from '@blazediff/gmsd';
|
|
2
3
|
|
|
3
|
-
interface
|
|
4
|
+
interface Image {
|
|
5
|
+
data: Buffer | Uint8Array | Uint8ClampedArray;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
interface Transformer {
|
|
10
|
+
transform: (input: string | Buffer) => Promise<Image>;
|
|
11
|
+
write: (image: Image, output: string | Buffer) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
type ComparisonMode = "diff" | "gmsd";
|
|
14
|
+
interface DiffModeOptions {
|
|
15
|
+
outputPath?: string;
|
|
16
|
+
transformer: Transformer;
|
|
17
|
+
mode?: "diff";
|
|
18
|
+
options?: CoreOptions;
|
|
19
|
+
}
|
|
20
|
+
interface GmsdModeOptions {
|
|
4
21
|
outputPath?: string;
|
|
5
|
-
transformer:
|
|
6
|
-
|
|
22
|
+
transformer: Transformer;
|
|
23
|
+
mode: "gmsd";
|
|
24
|
+
options?: GmsdOptions;
|
|
7
25
|
}
|
|
8
|
-
interface
|
|
26
|
+
interface DiffModeResult {
|
|
27
|
+
mode: "diff";
|
|
9
28
|
diffCount: number;
|
|
10
29
|
width: number;
|
|
11
30
|
height: number;
|
|
12
31
|
outputData?: Uint8Array;
|
|
13
32
|
duration: number;
|
|
14
33
|
}
|
|
15
|
-
|
|
34
|
+
interface GmsdModeResult {
|
|
35
|
+
mode: "gmsd";
|
|
36
|
+
score: number;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
outputData?: Uint8Array;
|
|
40
|
+
duration: number;
|
|
41
|
+
}
|
|
42
|
+
type BlazeDiffBinResult = DiffModeResult | GmsdModeResult;
|
|
43
|
+
declare function bin(image1Path: string, image2Path: string, options: GmsdModeOptions): Promise<GmsdModeResult>;
|
|
44
|
+
declare function bin(image1Path: string, image2Path: string, options: DiffModeOptions): Promise<DiffModeResult>;
|
|
16
45
|
|
|
17
|
-
export { type
|
|
46
|
+
export { type BlazeDiffBinResult, type ComparisonMode, type DiffModeOptions, type DiffModeResult, type GmsdModeOptions, type GmsdModeResult, type Image, type Transformer, bin as default };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var g=require('@blazediff/core'),p=require('@blazediff/gmsd');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var g__default=/*#__PURE__*/_interopDefault(g);var p__default=/*#__PURE__*/_interopDefault(p);var w=n=>n.mode==="gmsd";async function c(n,d,e){let[t,i]=await Promise.all([e.transformer.transform(n),e.transformer.transform(d)]);if(t.width!==i.width||t.height!==i.height)throw new Error(`Image dimensions do not match: ${t.width}x${t.height} vs ${i.width}x${i.height}`);if(w(e)){let o;e.outputPath&&(o=new Uint8Array(t.data.length));let m=performance.now(),u=p__default.default(t.data,i.data,o,t.width,t.height,e.options||{}),h=performance.now()-m;return e.outputPath&&o&&await e.transformer.write({data:o,width:t.width,height:t.height},e.outputPath),{mode:"gmsd",width:t.width,height:t.height,outputData:o,duration:h,score:u}}let r;e.outputPath&&(r=new Uint8Array(t.data.length));let s=performance.now(),a=g__default.default(t.data,i.data,r,t.width,t.height,e.options||{}),f=performance.now()-s;return a>0&&e.outputPath&&r&&await e.transformer.write({data:r,width:t.width,height:t.height},e.outputPath),{mode:"diff",diffCount:a,width:t.width,height:t.height,outputData:r,duration:f}}module.exports=c;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import g from'@blazediff/core';import p from'@blazediff/gmsd';var w=n=>n.mode==="gmsd";async function c(n,d,e){let[t,i]=await Promise.all([e.transformer.transform(n),e.transformer.transform(d)]);if(t.width!==i.width||t.height!==i.height)throw new Error(`Image dimensions do not match: ${t.width}x${t.height} vs ${i.width}x${i.height}`);if(w(e)){let o;e.outputPath&&(o=new Uint8Array(t.data.length));let m=performance.now(),u=p(t.data,i.data,o,t.width,t.height,e.options||{}),h=performance.now()-m;return e.outputPath&&o&&await e.transformer.write({data:o,width:t.width,height:t.height},e.outputPath),{mode:"gmsd",width:t.width,height:t.height,outputData:o,duration:h,score:u}}let r;e.outputPath&&(r=new Uint8Array(t.data.length));let s=performance.now(),a=g(t.data,i.data,r,t.width,t.height,e.options||{}),f=performance.now()-s;return a>0&&e.outputPath&&r&&await e.transformer.write({data:r,width:t.width,height:t.height},e.outputPath),{mode:"diff",diffCount:a,width:t.width,height:t.height,outputData:r,duration:f}}export{c as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blazediff/bin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Command-line interface for the blazediff image comparison library",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"homepage": "https://blazediff.dev",
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@blazediff/core": "1.
|
|
41
|
-
"@blazediff/
|
|
42
|
-
"@blazediff/
|
|
43
|
-
"@blazediff/
|
|
40
|
+
"@blazediff/core": "1.5.0",
|
|
41
|
+
"@blazediff/gmsd": "1.5.0",
|
|
42
|
+
"@blazediff/pngjs-transformer": "1.5.0",
|
|
43
|
+
"@blazediff/sharp-transformer": "1.5.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^24.3.0",
|