Initial commit
This commit is contained in:
commit
e49726988c
5445 files changed
+1089914
No files matched your search
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "../src",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext"
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "./build.json",
|
||||
"include": [
|
||||
"../src/**/*.ts",
|
||||
"../src/**/*.cts",
|
||||
"../src/**/*.tsx",
|
||||
"../src/**/*.json"
|
||||
],
|
||||
"exclude": [
|
||||
"../**/*.test.ts",
|
||||
"../src/**/*.mts",
|
||||
"../src/package.json"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "../.tshy-build/commonjs"
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "./build.json",
|
||||
"include": [
|
||||
"../src/**/*.ts",
|
||||
"../src/**/*.mts",
|
||||
"../src/**/*.tsx",
|
||||
"../src/**/*.json"
|
||||
],
|
||||
"exclude": [
|
||||
"../**/*.test.ts",
|
||||
"../src/package.json"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "../.tshy-build/esm"
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
> @jimp/diff@1.5.0 build /Users/andrewlisowski/Documents/jimp/packages/diff
|
||||
> tshy
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
> @jimp/diff@1.1.2 lint /Users/andrewlisowski/Documents/jimp/packages/diff
|
||||
> eslint .
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
> @jimp/diff@1.1.2 test /Users/andrewlisowski/Documents/jimp/packages/diff
|
||||
> vitest "--watch=false"
|
||||
|
||||
|
||||
[7m[1m[36m RUN [39m[22m[27m [36mv2.0.5[39m [90m/Users/andrewlisowski/Documents/jimp/packages/diff[39m
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# v1.1.3 (Mon Sep 02 2024)
|
||||
|
||||
#### 🐛 Bug Fix
|
||||
|
||||
- Update deps [#1319](https://github.com/jimp-dev/jimp/pull/1319) ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 1
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
---
|
||||
|
||||
# v1.1.2 (Mon Sep 02 2024)
|
||||
|
||||
#### 🐛 Bug Fix
|
||||
|
||||
- Jimp.diff() to make real resize before image compare [#1311](https://github.com/jimp-dev/jimp/pull/1311) ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 1
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
---
|
||||
|
||||
# v1.1.0 (Sun Sep 01 2024)
|
||||
|
||||
#### ⚠️ Pushed to `main`
|
||||
|
||||
- upgrade tshy ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 1
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
---
|
||||
|
||||
# v1.0.3 (Sat Aug 31 2024)
|
||||
|
||||
#### 🐛 Bug Fix
|
||||
|
||||
- Fix build [#1303](https://github.com/jimp-dev/jimp/pull/1303) ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### ⚠️ Pushed to `main`
|
||||
|
||||
- add clean script ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 1
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
---
|
||||
|
||||
# v1.0.2 (Sat Aug 31 2024)
|
||||
|
||||
#### ⚠️ Pushed to `main`
|
||||
|
||||
- set side effects ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
- fix versions ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
- add publish config ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 1
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Oliver Moran
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
/**
|
||||
* Diffs two images and returns
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @param threshold A number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
|
||||
* @returns An object with the following properties:
|
||||
* - percent: The proportion of different pixels (0-1), where 0 means the two images are pixel identical
|
||||
* - image: A Jimp image showing differences
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, diff } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* const diff = diff(image1, image2);
|
||||
*
|
||||
* diff.percent; // 0.5
|
||||
* diff.image; // a Jimp image showing differences
|
||||
* ```
|
||||
*/
|
||||
export declare function diff<I extends JimpClass>(img1: I, img2: I, threshold?: number): {
|
||||
percent: number;
|
||||
image: any;
|
||||
};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,SAAM;;;EA4C1E"}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.diff = diff;
|
||||
const plugin_resize_1 = require("@jimp/plugin-resize");
|
||||
const utils_1 = require("@jimp/utils");
|
||||
const pixelmatch_1 = __importDefault(require("pixelmatch"));
|
||||
/**
|
||||
* Diffs two images and returns
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @param threshold A number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
|
||||
* @returns An object with the following properties:
|
||||
* - percent: The proportion of different pixels (0-1), where 0 means the two images are pixel identical
|
||||
* - image: A Jimp image showing differences
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, diff } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* const diff = diff(image1, image2);
|
||||
*
|
||||
* diff.percent; // 0.5
|
||||
* diff.image; // a Jimp image showing differences
|
||||
* ```
|
||||
*/
|
||||
function diff(img1, img2, threshold = 0.1) {
|
||||
let bmp1 = img1.bitmap;
|
||||
let bmp2 = img2.bitmap;
|
||||
if (bmp1.width !== bmp2.width || bmp1.height !== bmp2.height) {
|
||||
if (bmp1.width * bmp1.height > bmp2.width * bmp2.height) {
|
||||
// img1 is bigger
|
||||
bmp1 = plugin_resize_1.methods.resize((0, utils_1.clone)(img1), {
|
||||
w: bmp2.width,
|
||||
h: bmp2.height,
|
||||
}).bitmap;
|
||||
}
|
||||
else {
|
||||
// img2 is bigger (or they are the same in area)
|
||||
bmp2 = plugin_resize_1.methods.resize((0, utils_1.clone)(img2), {
|
||||
w: bmp1.width,
|
||||
h: bmp1.height,
|
||||
}).bitmap;
|
||||
}
|
||||
}
|
||||
if (typeof threshold !== "number" || threshold < 0 || threshold > 1) {
|
||||
throw new Error("threshold must be a number between 0 and 1");
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const diff = new img1.constructor({
|
||||
width: bmp1.width,
|
||||
height: bmp1.height,
|
||||
color: 0xffffffff,
|
||||
});
|
||||
const numDiffPixels = (0, pixelmatch_1.default)(bmp1.data, bmp2.data, diff.bitmap.data, diff.bitmap.width, diff.bitmap.height, { threshold });
|
||||
return {
|
||||
percent: numDiffPixels / (diff.bitmap.width * diff.bitmap.height),
|
||||
image: diff,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;AA0BA,oBA4CC;AAtED,uDAA8C;AAE9C,uCAAoC;AACpC,4DAAoC;AAEpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,IAAI,CAAsB,IAAO,EAAE,IAAO,EAAE,SAAS,GAAG,GAAG;IACzE,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IAEvB,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACxD,iBAAiB;YACjB,IAAI,GAAG,uBAAO,CAAC,MAAM,CAAC,IAAA,aAAK,EAAC,IAAI,CAAC,EAAE;gBACjC,CAAC,EAAE,IAAI,CAAC,KAAK;gBACb,CAAC,EAAE,IAAI,CAAC,MAAM;aACf,CAAC,CAAC,MAAM,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,IAAI,GAAG,uBAAO,CAAC,MAAM,CAAC,IAAA,aAAK,EAAC,IAAI,CAAC,EAAE;gBACjC,CAAC,EAAE,IAAI,CAAC,KAAK;gBACb,CAAC,EAAE,IAAI,CAAC,MAAM;aACf,CAAC,CAAC,MAAM,CAAC;QACZ,CAAC;IACH,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,8DAA8D;IAC9D,MAAM,IAAI,GAAG,IAAK,IAAY,CAAC,WAAW,CAAC;QACzC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,UAAU;KAClB,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAA,oBAAU,EAC9B,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,IAAI,CAAC,MAAM,CAAC,KAAK,EACjB,IAAI,CAAC,MAAM,CAAC,MAAM,EAClB,EAAE,SAAS,EAAE,CACd,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,aAAa,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACjE,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
/**
|
||||
* Diffs two images and returns
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @param threshold A number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
|
||||
* @returns An object with the following properties:
|
||||
* - percent: The proportion of different pixels (0-1), where 0 means the two images are pixel identical
|
||||
* - image: A Jimp image showing differences
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, diff } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* const diff = diff(image1, image2);
|
||||
*
|
||||
* diff.percent; // 0.5
|
||||
* diff.image; // a Jimp image showing differences
|
||||
* ```
|
||||
*/
|
||||
export declare function diff<I extends JimpClass>(img1: I, img2: I, threshold?: number): {
|
||||
percent: number;
|
||||
image: any;
|
||||
};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,SAAM;;;EA4C1E"}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import { methods } from "@jimp/plugin-resize";
|
||||
import { clone } from "@jimp/utils";
|
||||
import pixelMatch from "pixelmatch";
|
||||
/**
|
||||
* Diffs two images and returns
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @param threshold A number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
|
||||
* @returns An object with the following properties:
|
||||
* - percent: The proportion of different pixels (0-1), where 0 means the two images are pixel identical
|
||||
* - image: A Jimp image showing differences
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, diff } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* const diff = diff(image1, image2);
|
||||
*
|
||||
* diff.percent; // 0.5
|
||||
* diff.image; // a Jimp image showing differences
|
||||
* ```
|
||||
*/
|
||||
export function diff(img1, img2, threshold = 0.1) {
|
||||
let bmp1 = img1.bitmap;
|
||||
let bmp2 = img2.bitmap;
|
||||
if (bmp1.width !== bmp2.width || bmp1.height !== bmp2.height) {
|
||||
if (bmp1.width * bmp1.height > bmp2.width * bmp2.height) {
|
||||
// img1 is bigger
|
||||
bmp1 = methods.resize(clone(img1), {
|
||||
w: bmp2.width,
|
||||
h: bmp2.height,
|
||||
}).bitmap;
|
||||
}
|
||||
else {
|
||||
// img2 is bigger (or they are the same in area)
|
||||
bmp2 = methods.resize(clone(img2), {
|
||||
w: bmp1.width,
|
||||
h: bmp1.height,
|
||||
}).bitmap;
|
||||
}
|
||||
}
|
||||
if (typeof threshold !== "number" || threshold < 0 || threshold > 1) {
|
||||
throw new Error("threshold must be a number between 0 and 1");
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const diff = new img1.constructor({
|
||||
width: bmp1.width,
|
||||
height: bmp1.height,
|
||||
color: 0xffffffff,
|
||||
});
|
||||
const numDiffPixels = pixelMatch(bmp1.data, bmp2.data, diff.bitmap.data, diff.bitmap.width, diff.bitmap.height, { threshold });
|
||||
return {
|
||||
percent: numDiffPixels / (diff.bitmap.width * diff.bitmap.height),
|
||||
image: diff,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,IAAI,CAAsB,IAAO,EAAE,IAAO,EAAE,SAAS,GAAG,GAAG;IACzE,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IAEvB,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACxD,iBAAiB;YACjB,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;gBACjC,CAAC,EAAE,IAAI,CAAC,KAAK;gBACb,CAAC,EAAE,IAAI,CAAC,MAAM;aACf,CAAC,CAAC,MAAM,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;gBACjC,CAAC,EAAE,IAAI,CAAC,KAAK;gBACb,CAAC,EAAE,IAAI,CAAC,MAAM;aACf,CAAC,CAAC,MAAM,CAAC;QACZ,CAAC;IACH,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,8DAA8D;IAC9D,MAAM,IAAI,GAAG,IAAK,IAAY,CAAC,WAAW,CAAC;QACzC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,UAAU;KAClB,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,UAAU,CAC9B,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,IAAI,CAAC,MAAM,CAAC,KAAK,EACjB,IAAI,CAAC,MAAM,CAAC,MAAM,EAClB,EAAE,SAAS,EAAE,CACd,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,aAAa,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACjE,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import shared from "@jimp/config-eslint/base.js";
|
||||
export default [...shared];
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../pixelmatch/bin/pixelmatch
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "@jimp/diff",
|
||||
"version": "1.6.0",
|
||||
"repository": "jimp-dev/jimp",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "vitest",
|
||||
"build": "tshy",
|
||||
"dev": "tshy --watch",
|
||||
"clean": "rm -rf node_modules .tshy .tshy-build dist .turbo"
|
||||
},
|
||||
"author": "Andrew Lisowski <lisowski54@gmail.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jimp/plugin-resize": "1.6.0",
|
||||
"@jimp/types": "1.6.0",
|
||||
"@jimp/utils": "1.6.0",
|
||||
"pixelmatch": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jimp/config-eslint": "1.6.0",
|
||||
"@jimp/config-typescript": "1.6.0",
|
||||
"@jimp/core": "1.6.0",
|
||||
"@jimp/test-utils": "1.6.0",
|
||||
"@types/pixelmatch": "^5.2.6",
|
||||
"eslint": "^9.9.1",
|
||||
"tshy": "^3.0.2",
|
||||
"typescript": "^5.5.4",
|
||||
"vitest": "^2.0.5"
|
||||
},
|
||||
"tshy": {
|
||||
"exclude": [
|
||||
"**/*.test.ts"
|
||||
],
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"main": "./dist/commonjs/index.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"module": "./dist/esm/index.js",
|
||||
"gitHead": "c88abe6046dccbdb6e4f5f00c3dd403c81d83515"
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Compare image difference > images 0 and 1 1`] = `
|
||||
Visualization:
|
||||
|
||||
D▴▴▴
|
||||
▴3▴▴
|
||||
▴▴◇▴
|
||||
▴▴▴▩
|
||||
|
||||
Data:
|
||||
|
||||
E8-E8-E8ᶠᶠ FF-00-00ᶠᶠ FF-00-00ᶠᶠ FF-00-00ᶠᶠ
|
||||
FF-00-00ᶠᶠ EC-EC-ECᶠᶠ FF-00-00ᶠᶠ FF-00-00ᶠᶠ
|
||||
FF-00-00ᶠᶠ FF-00-00ᶠᶠ EF-EF-EFᶠᶠ FF-00-00ᶠᶠ
|
||||
FF-00-00ᶠᶠ FF-00-00ᶠᶠ FF-00-00ᶠᶠ F3-F3-F3ᶠᶠ
|
||||
`;
|
||||
|
||||
exports[`Compare image difference > images 0 and 2 1`] = `
|
||||
Visualization:
|
||||
|
||||
DDDD
|
||||
3333
|
||||
◇◇◇◇
|
||||
▩▩▩▩
|
||||
|
||||
Data:
|
||||
|
||||
E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ
|
||||
EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ
|
||||
EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ
|
||||
F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ
|
||||
`;
|
||||
|
||||
exports[`Compare image difference > images 0 and 3 1`] = `
|
||||
Visualization:
|
||||
|
||||
DDDD
|
||||
3333
|
||||
◇◇◇◇
|
||||
▩▩▩▩
|
||||
|
||||
Data:
|
||||
|
||||
E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ E8-E8-E8ᶠᶠ
|
||||
EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ EC-EC-ECᶠᶠ
|
||||
EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ EF-EF-EFᶠᶠ
|
||||
F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ F3-F3-F3ᶠᶠ
|
||||
`;
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import { expect, test, describe } from "vitest";
|
||||
|
||||
import { makeTestImage } from "@jimp/test-utils";
|
||||
import { createJimp } from "@jimp/core";
|
||||
|
||||
import { diff } from "./index.js";
|
||||
|
||||
const Jimp = createJimp();
|
||||
|
||||
describe("Compare image difference", () => {
|
||||
const imgs = [
|
||||
Jimp.fromBitmap(makeTestImage("2222", "4444", "6666", "8888")),
|
||||
Jimp.fromBitmap(makeTestImage("2468", "2468", "2468", "2468")),
|
||||
Jimp.fromBitmap(makeTestImage("2212", "4434", "6656", "8878")),
|
||||
Jimp.fromBitmap(makeTestImage("2232", "4454", "6676", "8898")),
|
||||
Jimp.fromBitmap(makeTestImage("22322", "44544", "66766", "88988")),
|
||||
] as const;
|
||||
|
||||
test("images 0 and 1", () => {
|
||||
const result = diff(imgs[0], imgs[1]);
|
||||
|
||||
expect(result.percent).toBe(0.75);
|
||||
expect(result.image).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("images 0 and 2", () => {
|
||||
const result = diff(imgs[0], imgs[2]);
|
||||
|
||||
expect(result.percent).toBe(0);
|
||||
expect(result.image).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("images 0 and 3", () => {
|
||||
const result = diff(imgs[0], imgs[3]);
|
||||
|
||||
expect(result.percent).toBe(0);
|
||||
expect(result.image).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("allows to set a different threshold", () => {
|
||||
expect(diff(imgs[0], imgs[3], 0.1).percent).toBe(0);
|
||||
expect(diff(imgs[0], imgs[3], 0).percent).toBe(0.25);
|
||||
});
|
||||
|
||||
test("throws an error if threshold is invalid", () => {
|
||||
expect(() => diff(imgs[0], imgs[3], -1)).toThrow(
|
||||
"threshold must be a number between 0 and 1",
|
||||
);
|
||||
});
|
||||
|
||||
test("should resize image before diffing", () => {
|
||||
expect(diff(imgs[3], imgs[4]).percent).toStrictEqual(
|
||||
diff(imgs[4], imgs[3]).percent,
|
||||
);
|
||||
});
|
||||
});
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
import { methods } from "@jimp/plugin-resize";
|
||||
import { JimpClass } from "@jimp/types";
|
||||
import { clone } from "@jimp/utils";
|
||||
import pixelMatch from "pixelmatch";
|
||||
|
||||
/**
|
||||
* Diffs two images and returns
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @param threshold A number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
|
||||
* @returns An object with the following properties:
|
||||
* - percent: The proportion of different pixels (0-1), where 0 means the two images are pixel identical
|
||||
* - image: A Jimp image showing differences
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, diff } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* const diff = diff(image1, image2);
|
||||
*
|
||||
* diff.percent; // 0.5
|
||||
* diff.image; // a Jimp image showing differences
|
||||
* ```
|
||||
*/
|
||||
export function diff<I extends JimpClass>(img1: I, img2: I, threshold = 0.1) {
|
||||
let bmp1 = img1.bitmap;
|
||||
let bmp2 = img2.bitmap;
|
||||
|
||||
if (bmp1.width !== bmp2.width || bmp1.height !== bmp2.height) {
|
||||
if (bmp1.width * bmp1.height > bmp2.width * bmp2.height) {
|
||||
// img1 is bigger
|
||||
bmp1 = methods.resize(clone(img1), {
|
||||
w: bmp2.width,
|
||||
h: bmp2.height,
|
||||
}).bitmap;
|
||||
} else {
|
||||
// img2 is bigger (or they are the same in area)
|
||||
bmp2 = methods.resize(clone(img2), {
|
||||
w: bmp1.width,
|
||||
h: bmp1.height,
|
||||
}).bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof threshold !== "number" || threshold < 0 || threshold > 1) {
|
||||
throw new Error("threshold must be a number between 0 and 1");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const diff = new (img1 as any).constructor({
|
||||
width: bmp1.width,
|
||||
height: bmp1.height,
|
||||
color: 0xffffffff,
|
||||
});
|
||||
|
||||
const numDiffPixels = pixelMatch(
|
||||
bmp1.data,
|
||||
bmp2.data,
|
||||
diff.bitmap.data,
|
||||
diff.bitmap.width,
|
||||
diff.bitmap.height,
|
||||
{ threshold }
|
||||
);
|
||||
|
||||
return {
|
||||
percent: numDiffPixels / (diff.bitmap.width * diff.bitmap.height),
|
||||
image: diff,
|
||||
};
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "@jimp/config-typescript/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user