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/plugin-hash@1.5.0 build /Users/andrewlisowski/Documents/jimp/plugins/plugin-hash
|
||||
> tshy
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
> @jimp/plugin-hash@1.1.2 lint /Users/andrewlisowski/Documents/jimp/plugins/plugin-hash
|
||||
> eslint .
|
||||
|
||||
+983
@@ -0,0 +1,983 @@
|
||||
|
||||
> @jimp/plugin-hash@1.1.1 test:browser /Users/andrewlisowski/Documents/jimp/plugins/plugin-hash
|
||||
> vitest --config vitest.config.browser.mjs "--watch=false" "--u"
|
||||
|
||||
|
||||
[7m[1m[36m RUN [39m[22m[27m [36mv1.4.0[39m [90m/Users/andrewlisowski/Documents/jimp/plugins/plugin-hash[39m
|
||||
[2m[32m Browser runner started at http://localhost:5173/[39m[22m
|
||||
|
||||
[?25l [90m·[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[90m·[39m hash[2m (6)[22m
|
||||
[90m·[39m base 2
|
||||
[90m·[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠙[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠹[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠸[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠼[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠴[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠦[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠧[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[33m⠇[39m base 10 (decimal)
|
||||
[90m·[39m base 16 (hex)
|
||||
[90m·[39m base 64
|
||||
[90m·[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠇[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠏[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠋[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠙[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠹[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠸[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠼[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠴[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠦[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[33m❯[39m hash[2m (6)[22m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[33m⠧[39m base 23
|
||||
[90m·[39m base 17
|
||||
[90m·[39m pHash[2m (2)[22m
|
||||
[90m·[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠙[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠹[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠸[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠼[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠴[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[33m⠦[39m should calculate the distance using distanceFromHash
|
||||
[90m·[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[33m⠙[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[33m⠹[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[33m⠸[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [33m❯[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[33m❯[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[33m⠼[39m should calculate the distance using compareHashes.
|
||||
[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m[33m 1573[2mms[22m[39m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[32m✓[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[32m✓[39m should calculate the distance using compareHashes.
|
||||
[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m [2msrc/[22mindex[2m.test.ts[22m[2m (8)[22m[33m 1573[2mms[22m[39m
|
||||
[32m✓[39m hash[2m (6)[22m[33m 1367[2mms[22m[39m
|
||||
[32m✓[39m base 2
|
||||
[32m✓[39m base 10 (decimal)
|
||||
[32m✓[39m base 16 (hex)
|
||||
[32m✓[39m base 64
|
||||
[32m✓[39m base 23[33m 1044[2mms[22m[39m
|
||||
[32m✓[39m base 17
|
||||
[32m✓[39m pHash[2m (2)[22m
|
||||
[32m✓[39m should calculate the distance using distanceFromHash
|
||||
[32m✓[39m should calculate the distance using compareHashes.
|
||||
|
||||
[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
|
||||
[2m Tests [22m [1m[32m8 passed[39m[22m[90m (8)[39m
|
||||
[2m Start at [22m 00:42:17
|
||||
[2m Duration [22m 3.12s[2m (transform 0ms, setup 0ms, collect 124ms, tests 1.57s, environment 0ms, prepare 0ms)[22m
|
||||
|
||||
[?25h[?25h
|
||||
+2303
File diff suppressed because it is too large.
Load diff
+52
@@ -0,0 +1,52 @@
|
||||
# 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.0.5 (Sun Sep 01 2024)
|
||||
|
||||
#### 🐛 Bug Fix
|
||||
|
||||
- add missing dependency [#1306](https://github.com/jimp-dev/jimp/pull/1306) ([@benmccann](https://github.com/benmccann) [@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
|
||||
#### Authors: 2
|
||||
|
||||
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
|
||||
- Ben McCann ([@benmccann](https://github.com/benmccann))
|
||||
|
||||
---
|
||||
|
||||
# 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.
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
export declare const methods: {
|
||||
/**
|
||||
* Calculates the perceptual hash
|
||||
* @returns the perceptual hash
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash();
|
||||
* ```
|
||||
*/
|
||||
pHash<I extends JimpClass>(image: I): string;
|
||||
/**
|
||||
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
|
||||
* @param base A number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash(2); // binary
|
||||
* image.hash(64); // base 64
|
||||
* ```
|
||||
*/
|
||||
hash<I extends JimpClass>(image: I, base?: number): string;
|
||||
/**
|
||||
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
|
||||
* @param compareHash hash to compare to
|
||||
* @returns a number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.distanceFromHash(image.pHash());
|
||||
* ```
|
||||
*/
|
||||
distanceFromHash<I extends JimpClass>(image: I, compareHash: string): number;
|
||||
};
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, distance } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* distance(image1, image2); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export declare function distance<I extends JimpClass>(img1: I, img2: I): number;
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param hash1 A pHash
|
||||
* @param hash2 A pHash
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, compareHashes } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* compareHashes(image1.pHash(), image2.pHash()); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export declare function compareHashes(hash1: string, hash2: string): number;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxC,eAAO,MAAM,OAAO;IAClB;;;;;;;;;;;OAWG;UACG,CAAC,SAAS,SAAS,SAAS,CAAC;IAKnC;;;;;;;;;;;;OAYG;SACE,CAAC,SAAS,SAAS,SAAS,CAAC;IAYlC;;;;;;;;;;;;OAYG;qBACc,CAAC,SAAS,SAAS,SAAS,CAAC,eAAe,MAAM;CAMpE,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,UAM7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAGzD"}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.methods = void 0;
|
||||
exports.distance = distance;
|
||||
exports.compareHashes = compareHashes;
|
||||
const any_base_1 = __importDefault(require("any-base"));
|
||||
const phash_js_1 = __importDefault(require("./phash.js"));
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
// prettier-ignore
|
||||
const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
const maxHashLength = [NaN, NaN];
|
||||
for (let i = 2; i < 65; i++) {
|
||||
const maxHash = (0, any_base_1.default)(any_base_1.default.BIN, alphabet.slice(0, i))(new Array(64 + 1).join("1"));
|
||||
maxHashLength.push(maxHash.length);
|
||||
}
|
||||
exports.methods = {
|
||||
/**
|
||||
* Calculates the perceptual hash
|
||||
* @returns the perceptual hash
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash();
|
||||
* ```
|
||||
*/
|
||||
pHash(image) {
|
||||
const pHash = new phash_js_1.default();
|
||||
return pHash.getHash(image);
|
||||
},
|
||||
/**
|
||||
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
|
||||
* @param base A number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash(2); // binary
|
||||
* image.hash(64); // base 64
|
||||
* ```
|
||||
*/
|
||||
hash(image, base = 64) {
|
||||
if (base < 2 || base > 64) {
|
||||
throw new Error("base must be a number between 2 and 64");
|
||||
}
|
||||
const subAlphabet = alphabet.slice(0, base);
|
||||
const pHash = this.pHash(image);
|
||||
const maxLength = maxHashLength[base];
|
||||
return (0, any_base_1.default)(any_base_1.default.BIN, subAlphabet)(pHash).padStart(maxLength, "0");
|
||||
},
|
||||
/**
|
||||
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
|
||||
* @param compareHash hash to compare to
|
||||
* @returns a number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.distanceFromHash(image.pHash());
|
||||
* ```
|
||||
*/
|
||||
distanceFromHash(image, compareHash) {
|
||||
const pHash = new phash_js_1.default();
|
||||
const currentHash = pHash.getHash(image);
|
||||
return pHash.distance(currentHash, compareHash);
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, distance } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* distance(image1, image2); // 0.5
|
||||
* ```
|
||||
*/
|
||||
function distance(img1, img2) {
|
||||
const phash = new phash_js_1.default();
|
||||
const hash1 = phash.getHash(img1);
|
||||
const hash2 = phash.getHash(img2);
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param hash1 A pHash
|
||||
* @param hash2 A pHash
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, compareHashes } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* compareHashes(image1.pHash(), image2.pHash()); // 0.5
|
||||
* ```
|
||||
*/
|
||||
function compareHashes(hash1, hash2) {
|
||||
const phash = new phash_js_1.default();
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAsGA,4BAMC;AAiBD,sCAGC;AA/HD,wDAA+B;AAE/B,0DAAoC;AAEpC,wEAAwE;AACxE,gDAAgD;AAChD,kBAAkB;AAClB,MAAM,QAAQ,GACZ,kEAAkE,CAAC;AAErE,wEAAwE;AACxE,gDAAgD;AAChD,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAA,kBAAO,EACrB,kBAAO,CAAC,GAAG,EACX,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACrB,CAAC,IAAI,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAEY,QAAA,OAAO,GAAG;IACrB;;;;;;;;;;;OAWG;IACH,KAAK,CAAsB,KAAQ;QACjC,MAAM,KAAK,GAAG,IAAI,kBAAU,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,CAAsB,KAAQ,EAAE,IAAI,GAAG,EAAE;QAC3C,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAE,CAAC;QAEvC,OAAO,IAAA,kBAAO,EAAC,kBAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAsB,KAAQ,EAAE,WAAmB;QACjE,MAAM,KAAK,GAAG,IAAI,kBAAU,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEzC,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAClD,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,SAAgB,QAAQ,CAAsB,IAAO,EAAE,IAAO;IAC5D,MAAM,KAAK,GAAG,IAAI,kBAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,aAAa,CAAC,KAAa,EAAE,KAAa;IACxD,MAAM,KAAK,GAAG,IAAI,kBAAU,EAAE,CAAC;IAC/B,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
declare class ImagePHash {
|
||||
size: number;
|
||||
smallerSize: number;
|
||||
constructor(size?: number, smallerSize?: number);
|
||||
distance(s1: string, s2: string): number;
|
||||
/**
|
||||
* Returns a 'binary string' (like. 001010111011100010) which is easy to do a hamming distance on.
|
||||
*/
|
||||
getHash(img: JimpClass): string;
|
||||
}
|
||||
export default ImagePHash;
|
||||
//# sourceMappingURL=phash.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"phash.d.ts","sourceRoot":"","sources":["../../src/phash.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAWxC,cAAM,UAAU;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;gBAER,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAM/C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAY/B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,SAAS;CAyEvB;AAuDD,eAAe,UAAU,CAAC"}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
"use strict";
|
||||
/*
|
||||
Copyright (c) 2011 Elliot Shepherd
|
||||
|
||||
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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const plugin_color_1 = require("@jimp/plugin-color");
|
||||
const plugin_resize_1 = require("@jimp/plugin-resize");
|
||||
const utils_1 = require("@jimp/utils");
|
||||
// https://code.google.com/p/ironchef-team21/source/browse/ironchef_team21/src/ImagePHash.java
|
||||
/*
|
||||
* pHash-like image hash.
|
||||
* Author: Elliot Shepherd (elliot@jarofworms.com
|
||||
* Based On: http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
||||
*/
|
||||
class ImagePHash {
|
||||
size;
|
||||
smallerSize;
|
||||
constructor(size, smallerSize) {
|
||||
this.size = size || 32;
|
||||
this.smallerSize = smallerSize || 8;
|
||||
initCoefficients(this.size);
|
||||
}
|
||||
distance(s1, s2) {
|
||||
let counter = 0;
|
||||
for (let k = 0; k < s1.length; k++) {
|
||||
if (s1[k] !== s2[k]) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
return counter / s1.length;
|
||||
}
|
||||
/**
|
||||
* Returns a 'binary string' (like. 001010111011100010) which is easy to do a hamming distance on.
|
||||
*/
|
||||
getHash(img) {
|
||||
/* 1. Reduce size.
|
||||
* Like Average Hash, pHash starts with a small image.
|
||||
* However, the image is larger than 8x8; 32x32 is a good size.
|
||||
* This is really done to simplify the DCT computation and not
|
||||
* because it is needed to reduce the high frequencies.
|
||||
*/
|
||||
img = plugin_resize_1.methods.resize((0, utils_1.clone)(img), { w: this.size, h: this.size });
|
||||
/* 2. Reduce color.
|
||||
* The image is reduced to a grayscale just to further simplify
|
||||
* the number of computations.
|
||||
*/
|
||||
img = plugin_color_1.methods.greyscale(img);
|
||||
const vals = [];
|
||||
for (let x = 0; x < img.bitmap.width; x++) {
|
||||
const row = [];
|
||||
for (let y = 0; y < img.bitmap.height; y++) {
|
||||
row[y] = intToRGBA(img.getPixelColor(x, y)).b;
|
||||
}
|
||||
vals[x] = row;
|
||||
}
|
||||
/* 3. Compute the DCT.
|
||||
* The DCT separates the image into a collection of frequencies
|
||||
* and scalars. While JPEG uses an 8x8 DCT, this algorithm uses
|
||||
* a 32x32 DCT.
|
||||
*/
|
||||
const dctVals = applyDCT(vals, this.size);
|
||||
/* 4. Reduce the DCT.
|
||||
* This is the magic step. While the DCT is 32x32, just keep the
|
||||
* top-left 8x8. Those represent the lowest frequencies in the
|
||||
* picture.
|
||||
*/
|
||||
/* 5. Compute the average value.
|
||||
* Like the Average Hash, compute the mean DCT value (using only
|
||||
* the 8x8 DCT low-frequency values and excluding the first term
|
||||
* since the DC coefficient can be significantly different from
|
||||
* the other values and will throw off the average).
|
||||
*/
|
||||
let total = 0;
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
total += dctVals[x][y];
|
||||
}
|
||||
}
|
||||
const avg = total / (this.smallerSize * this.smallerSize);
|
||||
/* 6. Further reduce the DCT.
|
||||
* This is the magic step. Set the 64 hash bits to 0 or 1
|
||||
* depending on whether each of the 64 DCT values is above or
|
||||
* below the average value. The result doesn't tell us the
|
||||
* actual low frequencies; it just tells us the very-rough
|
||||
* relative scale of the frequencies to the mean. The result
|
||||
* will not vary as long as the overall structure of the image
|
||||
* remains the same; this can survive gamma and color histogram
|
||||
* adjustments without a problem.
|
||||
*/
|
||||
let hash = "";
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
hash += dctVals[x][y] > avg ? "1" : "0";
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
// DCT function stolen from http://stackoverflow.com/questions/4240490/problems-with-dct-and-idct-algorithm-in-java
|
||||
/**
|
||||
Convert a 32-bit integer color value to an RGBA object.
|
||||
*/
|
||||
function intToRGBA(i) {
|
||||
const a = i & 0xff;
|
||||
i >>>= 8;
|
||||
const b = i & 0xff;
|
||||
i >>>= 8;
|
||||
const g = i & 0xff;
|
||||
i >>>= 8;
|
||||
const r = i & 0xff;
|
||||
return { r, g, b, a };
|
||||
}
|
||||
const c = [];
|
||||
function initCoefficients(size) {
|
||||
for (let i = 1; i < size; i++) {
|
||||
c[i] = 1;
|
||||
}
|
||||
c[0] = 1 / Math.sqrt(2.0);
|
||||
}
|
||||
function applyDCT(f, size) {
|
||||
const N = size;
|
||||
const F = [];
|
||||
for (let u = 0; u < N; u++) {
|
||||
const row = [];
|
||||
for (let v = 0; v < N; v++) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < N; j++) {
|
||||
sum +=
|
||||
Math.cos(((2 * i + 1) / (2.0 * N)) * u * Math.PI) *
|
||||
Math.cos(((2 * j + 1) / (2.0 * N)) * v * Math.PI) *
|
||||
f[i][j];
|
||||
}
|
||||
}
|
||||
sum *= (c[u] * c[v]) / 4;
|
||||
row[v] = sum;
|
||||
F[u] = row;
|
||||
}
|
||||
}
|
||||
return F;
|
||||
}
|
||||
exports.default = ImagePHash;
|
||||
//# sourceMappingURL=phash.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"phash.js","sourceRoot":"","sources":["../../src/phash.ts"],"names":[],"mappings":"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"}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
export declare const methods: {
|
||||
/**
|
||||
* Calculates the perceptual hash
|
||||
* @returns the perceptual hash
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash();
|
||||
* ```
|
||||
*/
|
||||
pHash<I extends JimpClass>(image: I): string;
|
||||
/**
|
||||
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
|
||||
* @param base A number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash(2); // binary
|
||||
* image.hash(64); // base 64
|
||||
* ```
|
||||
*/
|
||||
hash<I extends JimpClass>(image: I, base?: number): string;
|
||||
/**
|
||||
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
|
||||
* @param compareHash hash to compare to
|
||||
* @returns a number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.distanceFromHash(image.pHash());
|
||||
* ```
|
||||
*/
|
||||
distanceFromHash<I extends JimpClass>(image: I, compareHash: string): number;
|
||||
};
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, distance } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* distance(image1, image2); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export declare function distance<I extends JimpClass>(img1: I, img2: I): number;
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param hash1 A pHash
|
||||
* @param hash2 A pHash
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, compareHashes } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* compareHashes(image1.pHash(), image2.pHash()); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export declare function compareHashes(hash1: string, hash2: string): number;
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxC,eAAO,MAAM,OAAO;IAClB;;;;;;;;;;;OAWG;UACG,CAAC,SAAS,SAAS,SAAS,CAAC;IAKnC;;;;;;;;;;;;OAYG;SACE,CAAC,SAAS,SAAS,SAAS,CAAC;IAYlC;;;;;;;;;;;;OAYG;qBACc,CAAC,SAAS,SAAS,SAAS,CAAC,eAAe,MAAM;CAMpE,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,UAM7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAGzD"}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
import anyBase from "any-base";
|
||||
import ImagePHash from "./phash.js";
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
// prettier-ignore
|
||||
const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
const maxHashLength = [NaN, NaN];
|
||||
for (let i = 2; i < 65; i++) {
|
||||
const maxHash = anyBase(anyBase.BIN, alphabet.slice(0, i))(new Array(64 + 1).join("1"));
|
||||
maxHashLength.push(maxHash.length);
|
||||
}
|
||||
export const methods = {
|
||||
/**
|
||||
* Calculates the perceptual hash
|
||||
* @returns the perceptual hash
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash();
|
||||
* ```
|
||||
*/
|
||||
pHash(image) {
|
||||
const pHash = new ImagePHash();
|
||||
return pHash.getHash(image);
|
||||
},
|
||||
/**
|
||||
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
|
||||
* @param base A number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash(2); // binary
|
||||
* image.hash(64); // base 64
|
||||
* ```
|
||||
*/
|
||||
hash(image, base = 64) {
|
||||
if (base < 2 || base > 64) {
|
||||
throw new Error("base must be a number between 2 and 64");
|
||||
}
|
||||
const subAlphabet = alphabet.slice(0, base);
|
||||
const pHash = this.pHash(image);
|
||||
const maxLength = maxHashLength[base];
|
||||
return anyBase(anyBase.BIN, subAlphabet)(pHash).padStart(maxLength, "0");
|
||||
},
|
||||
/**
|
||||
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
|
||||
* @param compareHash hash to compare to
|
||||
* @returns a number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.distanceFromHash(image.pHash());
|
||||
* ```
|
||||
*/
|
||||
distanceFromHash(image, compareHash) {
|
||||
const pHash = new ImagePHash();
|
||||
const currentHash = pHash.getHash(image);
|
||||
return pHash.distance(currentHash, compareHash);
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, distance } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* distance(image1, image2); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export function distance(img1, img2) {
|
||||
const phash = new ImagePHash();
|
||||
const hash1 = phash.getHash(img1);
|
||||
const hash2 = phash.getHash(img2);
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param hash1 A pHash
|
||||
* @param hash2 A pHash
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, compareHashes } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* compareHashes(image1.pHash(), image2.pHash()); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export function compareHashes(hash1, hash2) {
|
||||
const phash = new ImagePHash();
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,UAAU,CAAC;AAE/B,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,wEAAwE;AACxE,gDAAgD;AAChD,kBAAkB;AAClB,MAAM,QAAQ,GACZ,kEAAkE,CAAC;AAErE,wEAAwE;AACxE,gDAAgD;AAChD,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,OAAO,CACrB,OAAO,CAAC,GAAG,EACX,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACrB,CAAC,IAAI,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;;;;;;;;;;;OAWG;IACH,KAAK,CAAsB,KAAQ;QACjC,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,IAAI,CAAsB,KAAQ,EAAE,IAAI,GAAG,EAAE;QAC3C,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAE,CAAC;QAEvC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAsB,KAAQ,EAAE,WAAmB;QACjE,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAEzC,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAClD,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAAsB,IAAO,EAAE,IAAO;IAC5D,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,KAAa;IACxD,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
declare class ImagePHash {
|
||||
size: number;
|
||||
smallerSize: number;
|
||||
constructor(size?: number, smallerSize?: number);
|
||||
distance(s1: string, s2: string): number;
|
||||
/**
|
||||
* Returns a 'binary string' (like. 001010111011100010) which is easy to do a hamming distance on.
|
||||
*/
|
||||
getHash(img: JimpClass): string;
|
||||
}
|
||||
export default ImagePHash;
|
||||
//# sourceMappingURL=phash.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"phash.d.ts","sourceRoot":"","sources":["../../src/phash.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAWxC,cAAM,UAAU;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;gBAER,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAM/C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAY/B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,SAAS;CAyEvB;AAuDD,eAAe,UAAU,CAAC"}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
Copyright (c) 2011 Elliot Shepherd
|
||||
|
||||
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.
|
||||
*/
|
||||
import { methods as color } from "@jimp/plugin-color";
|
||||
import { methods } from "@jimp/plugin-resize";
|
||||
import { clone } from "@jimp/utils";
|
||||
// https://code.google.com/p/ironchef-team21/source/browse/ironchef_team21/src/ImagePHash.java
|
||||
/*
|
||||
* pHash-like image hash.
|
||||
* Author: Elliot Shepherd (elliot@jarofworms.com
|
||||
* Based On: http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
||||
*/
|
||||
class ImagePHash {
|
||||
size;
|
||||
smallerSize;
|
||||
constructor(size, smallerSize) {
|
||||
this.size = size || 32;
|
||||
this.smallerSize = smallerSize || 8;
|
||||
initCoefficients(this.size);
|
||||
}
|
||||
distance(s1, s2) {
|
||||
let counter = 0;
|
||||
for (let k = 0; k < s1.length; k++) {
|
||||
if (s1[k] !== s2[k]) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
return counter / s1.length;
|
||||
}
|
||||
/**
|
||||
* Returns a 'binary string' (like. 001010111011100010) which is easy to do a hamming distance on.
|
||||
*/
|
||||
getHash(img) {
|
||||
/* 1. Reduce size.
|
||||
* Like Average Hash, pHash starts with a small image.
|
||||
* However, the image is larger than 8x8; 32x32 is a good size.
|
||||
* This is really done to simplify the DCT computation and not
|
||||
* because it is needed to reduce the high frequencies.
|
||||
*/
|
||||
img = methods.resize(clone(img), { w: this.size, h: this.size });
|
||||
/* 2. Reduce color.
|
||||
* The image is reduced to a grayscale just to further simplify
|
||||
* the number of computations.
|
||||
*/
|
||||
img = color.greyscale(img);
|
||||
const vals = [];
|
||||
for (let x = 0; x < img.bitmap.width; x++) {
|
||||
const row = [];
|
||||
for (let y = 0; y < img.bitmap.height; y++) {
|
||||
row[y] = intToRGBA(img.getPixelColor(x, y)).b;
|
||||
}
|
||||
vals[x] = row;
|
||||
}
|
||||
/* 3. Compute the DCT.
|
||||
* The DCT separates the image into a collection of frequencies
|
||||
* and scalars. While JPEG uses an 8x8 DCT, this algorithm uses
|
||||
* a 32x32 DCT.
|
||||
*/
|
||||
const dctVals = applyDCT(vals, this.size);
|
||||
/* 4. Reduce the DCT.
|
||||
* This is the magic step. While the DCT is 32x32, just keep the
|
||||
* top-left 8x8. Those represent the lowest frequencies in the
|
||||
* picture.
|
||||
*/
|
||||
/* 5. Compute the average value.
|
||||
* Like the Average Hash, compute the mean DCT value (using only
|
||||
* the 8x8 DCT low-frequency values and excluding the first term
|
||||
* since the DC coefficient can be significantly different from
|
||||
* the other values and will throw off the average).
|
||||
*/
|
||||
let total = 0;
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
total += dctVals[x][y];
|
||||
}
|
||||
}
|
||||
const avg = total / (this.smallerSize * this.smallerSize);
|
||||
/* 6. Further reduce the DCT.
|
||||
* This is the magic step. Set the 64 hash bits to 0 or 1
|
||||
* depending on whether each of the 64 DCT values is above or
|
||||
* below the average value. The result doesn't tell us the
|
||||
* actual low frequencies; it just tells us the very-rough
|
||||
* relative scale of the frequencies to the mean. The result
|
||||
* will not vary as long as the overall structure of the image
|
||||
* remains the same; this can survive gamma and color histogram
|
||||
* adjustments without a problem.
|
||||
*/
|
||||
let hash = "";
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
hash += dctVals[x][y] > avg ? "1" : "0";
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
// DCT function stolen from http://stackoverflow.com/questions/4240490/problems-with-dct-and-idct-algorithm-in-java
|
||||
/**
|
||||
Convert a 32-bit integer color value to an RGBA object.
|
||||
*/
|
||||
function intToRGBA(i) {
|
||||
const a = i & 0xff;
|
||||
i >>>= 8;
|
||||
const b = i & 0xff;
|
||||
i >>>= 8;
|
||||
const g = i & 0xff;
|
||||
i >>>= 8;
|
||||
const r = i & 0xff;
|
||||
return { r, g, b, a };
|
||||
}
|
||||
const c = [];
|
||||
function initCoefficients(size) {
|
||||
for (let i = 1; i < size; i++) {
|
||||
c[i] = 1;
|
||||
}
|
||||
c[0] = 1 / Math.sqrt(2.0);
|
||||
}
|
||||
function applyDCT(f, size) {
|
||||
const N = size;
|
||||
const F = [];
|
||||
for (let u = 0; u < N; u++) {
|
||||
const row = [];
|
||||
for (let v = 0; v < N; v++) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < N; j++) {
|
||||
sum +=
|
||||
Math.cos(((2 * i + 1) / (2.0 * N)) * u * Math.PI) *
|
||||
Math.cos(((2 * j + 1) / (2.0 * N)) * v * Math.PI) *
|
||||
f[i][j];
|
||||
}
|
||||
}
|
||||
sum *= (c[u] * c[v]) / 4;
|
||||
row[v] = sum;
|
||||
F[u] = row;
|
||||
}
|
||||
}
|
||||
return F;
|
||||
}
|
||||
export default ImagePHash;
|
||||
//# sourceMappingURL=phash.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"phash.js","sourceRoot":"","sources":["../../src/phash.ts"],"names":[],"mappings":"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"}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import shared from "@jimp/config-eslint/base.js";
|
||||
export default [...shared];
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"name": "@jimp/plugin-hash",
|
||||
"version": "1.6.0",
|
||||
"repository": "jimp-dev/jimp",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "vitest",
|
||||
"test:browser": "vitest --config vitest.config.browser.mjs",
|
||||
"build": "tshy",
|
||||
"dev": "tshy --watch",
|
||||
"clean": "rm -rf node_modules .tshy .tshy-build dist .turbo"
|
||||
},
|
||||
"author": "Andrew Lisowski <lisowski54@gmail.com>",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@jimp/config-eslint": "1.6.0",
|
||||
"@jimp/config-typescript": "1.6.0",
|
||||
"@jimp/config-vitest": "1.6.0",
|
||||
"@jimp/test-utils": "1.6.0",
|
||||
"@types/any-base": "^1.1.3",
|
||||
"@vitest/browser": "^2.0.5",
|
||||
"eslint": "^9.9.1",
|
||||
"tshy": "^3.0.2",
|
||||
"typescript": "^5.5.4",
|
||||
"vite-plugin-node-polyfills": "^0.22.0",
|
||||
"vitest": "^2.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jimp/core": "1.6.0",
|
||||
"@jimp/js-bmp": "1.6.0",
|
||||
"@jimp/js-jpeg": "1.6.0",
|
||||
"@jimp/js-png": "1.6.0",
|
||||
"@jimp/js-tiff": "1.6.0",
|
||||
"@jimp/plugin-color": "1.6.0",
|
||||
"@jimp/plugin-resize": "1.6.0",
|
||||
"@jimp/types": "1.6.0",
|
||||
"@jimp/utils": "1.6.0",
|
||||
"any-base": "^1.1.0"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
import { expect, test, describe } from "vitest";
|
||||
import { getTestImagePath } from "@jimp/test-utils";
|
||||
import { createJimp } from "@jimp/core";
|
||||
import bmp from "@jimp/js-bmp";
|
||||
import png from "@jimp/js-png";
|
||||
import jpeg from "@jimp/js-jpeg";
|
||||
import tiff from "@jimp/js-tiff";
|
||||
|
||||
import { methods, compareHashes, distance } from "./index.js";
|
||||
|
||||
const Jimp = createJimp({
|
||||
formats: [bmp, png, jpeg, tiff],
|
||||
plugins: [methods],
|
||||
});
|
||||
|
||||
describe("hash", () => {
|
||||
test("base 2", async () => {
|
||||
const image = await Jimp.read(getTestImagePath("dice.png"));
|
||||
|
||||
expect(image.hash(2)).toBe(
|
||||
"1100010000011111011010111110000000010101001011010101101000010010",
|
||||
);
|
||||
});
|
||||
|
||||
test("base 10 (decimal)", async () => {
|
||||
const image = await Jimp.read(getTestImagePath("cops.jpg"));
|
||||
|
||||
expect(image.hash(10)).toBe("13442314021806033441");
|
||||
});
|
||||
|
||||
test("base 16 (hex)", async () => {
|
||||
const image = await Jimp.read(getTestImagePath("rgb.tiff"));
|
||||
|
||||
expect(image.hash(16)).toBe("949800481007044c");
|
||||
});
|
||||
|
||||
test("base 64", async () => {
|
||||
const image = await Jimp.read(getTestImagePath("windows95.bmp"));
|
||||
|
||||
expect(image.hash(64)).toBe("fb0xj0Mw400");
|
||||
});
|
||||
|
||||
test("base 23", async function () {
|
||||
const image = await Jimp.read(getTestImagePath("panoramic.jpg"));
|
||||
|
||||
expect(image.hash(23)).toBe("0m1m2id7l7cl4fb");
|
||||
});
|
||||
|
||||
test("base 17", async () => {
|
||||
const image = await Jimp.read(getTestImagePath("dice.png"));
|
||||
|
||||
expect(image.hash(17)).toBe("4ffe16bf68eee351");
|
||||
});
|
||||
});
|
||||
|
||||
describe("pHash", () => {
|
||||
test("should calculate the distance using distanceFromHash", async function () {
|
||||
const image1 = await Jimp.read(getTestImagePath("dice.png"));
|
||||
const image2 = await Jimp.read(getTestImagePath("mask.png"));
|
||||
|
||||
const hash = image1.pHash();
|
||||
|
||||
expect(image2.distanceFromHash(hash)).toBe(distance(image1, image2));
|
||||
});
|
||||
|
||||
test("should calculate the distance using compareHashes.", async function () {
|
||||
const image1 = await Jimp.read(getTestImagePath("dice.png"));
|
||||
const image2 = await Jimp.read(getTestImagePath("mask.png"));
|
||||
|
||||
const hash1 = image1.pHash();
|
||||
const hash2 = image2.pHash();
|
||||
|
||||
expect(compareHashes(hash1, hash2)).toBe(distance(image1, image2));
|
||||
});
|
||||
});
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
import { JimpClass } from "@jimp/types";
|
||||
import anyBase from "any-base";
|
||||
|
||||
import ImagePHash from "./phash.js";
|
||||
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
// prettier-ignore
|
||||
const alphabet =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
|
||||
|
||||
// an array storing the maximum string length of hashes at various bases
|
||||
// 0 and 1 do not exist as possible hash lengths
|
||||
const maxHashLength = [NaN, NaN];
|
||||
|
||||
for (let i = 2; i < 65; i++) {
|
||||
const maxHash = anyBase(
|
||||
anyBase.BIN,
|
||||
alphabet.slice(0, i),
|
||||
)(new Array(64 + 1).join("1"));
|
||||
maxHashLength.push(maxHash.length);
|
||||
}
|
||||
|
||||
export const methods = {
|
||||
/**
|
||||
* Calculates the perceptual hash
|
||||
* @returns the perceptual hash
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash();
|
||||
* ```
|
||||
*/
|
||||
pHash<I extends JimpClass>(image: I) {
|
||||
const pHash = new ImagePHash();
|
||||
return pHash.getHash(image);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
|
||||
* @param base A number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.hash(2); // binary
|
||||
* image.hash(64); // base 64
|
||||
* ```
|
||||
*/
|
||||
hash<I extends JimpClass>(image: I, base = 64) {
|
||||
if (base < 2 || base > 64) {
|
||||
throw new Error("base must be a number between 2 and 64");
|
||||
}
|
||||
|
||||
const subAlphabet = alphabet.slice(0, base);
|
||||
const pHash = this.pHash(image);
|
||||
const maxLength = maxHashLength[base]!;
|
||||
|
||||
return anyBase(anyBase.BIN, subAlphabet)(pHash).padStart(maxLength, "0");
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
|
||||
* @param compareHash hash to compare to
|
||||
* @returns a number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp } from "jimp";
|
||||
*
|
||||
* const image = await Jimp.read("test/image.png");
|
||||
*
|
||||
* image.distanceFromHash(image.pHash());
|
||||
* ```
|
||||
*/
|
||||
distanceFromHash<I extends JimpClass>(image: I, compareHash: string) {
|
||||
const pHash = new ImagePHash();
|
||||
const currentHash = pHash.getHash(image);
|
||||
|
||||
return pHash.distance(currentHash, compareHash);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param img1 A Jimp image to compare
|
||||
* @param img2 A Jimp image to compare
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, distance } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* distance(image1, image2); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export function distance<I extends JimpClass>(img1: I, img2: I) {
|
||||
const phash = new ImagePHash();
|
||||
const hash1 = phash.getHash(img1);
|
||||
const hash2 = phash.getHash(img2);
|
||||
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the hamming distance of two images based on their perceptual hash
|
||||
* @param hash1 A pHash
|
||||
* @param hash2 A pHash
|
||||
* @returns A number ranging from 0 to 1, 0 means they are believed to be identical
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Jimp, compareHashes } from "jimp";
|
||||
*
|
||||
* const image1 = await Jimp.read("test/image.png");
|
||||
* const image2 = await Jimp.read("test/image.png");
|
||||
*
|
||||
* compareHashes(image1.pHash(), image2.pHash()); // 0.5
|
||||
* ```
|
||||
*/
|
||||
export function compareHashes(hash1: string, hash2: string) {
|
||||
const phash = new ImagePHash();
|
||||
return phash.distance(hash1, hash2);
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
Copyright (c) 2011 Elliot Shepherd
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
import { methods as color } from "@jimp/plugin-color";
|
||||
import { methods } from "@jimp/plugin-resize";
|
||||
import { JimpClass } from "@jimp/types";
|
||||
import { clone } from "@jimp/utils";
|
||||
|
||||
// https://code.google.com/p/ironchef-team21/source/browse/ironchef_team21/src/ImagePHash.java
|
||||
|
||||
/*
|
||||
* pHash-like image hash.
|
||||
* Author: Elliot Shepherd (elliot@jarofworms.com
|
||||
* Based On: http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
||||
*/
|
||||
|
||||
class ImagePHash {
|
||||
size: number;
|
||||
smallerSize: number;
|
||||
|
||||
constructor(size?: number, smallerSize?: number) {
|
||||
this.size = size || 32;
|
||||
this.smallerSize = smallerSize || 8;
|
||||
initCoefficients(this.size);
|
||||
}
|
||||
|
||||
distance(s1: string, s2: string) {
|
||||
let counter = 0;
|
||||
|
||||
for (let k = 0; k < s1.length; k++) {
|
||||
if (s1[k] !== s2[k]) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return counter / s1.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a 'binary string' (like. 001010111011100010) which is easy to do a hamming distance on.
|
||||
*/
|
||||
getHash(img: JimpClass) {
|
||||
/* 1. Reduce size.
|
||||
* Like Average Hash, pHash starts with a small image.
|
||||
* However, the image is larger than 8x8; 32x32 is a good size.
|
||||
* This is really done to simplify the DCT computation and not
|
||||
* because it is needed to reduce the high frequencies.
|
||||
*/
|
||||
img = methods.resize(clone(img), { w: this.size, h: this.size });
|
||||
|
||||
/* 2. Reduce color.
|
||||
* The image is reduced to a grayscale just to further simplify
|
||||
* the number of computations.
|
||||
*/
|
||||
img = color.greyscale(img);
|
||||
|
||||
const vals = [];
|
||||
|
||||
for (let x = 0; x < img.bitmap.width; x++) {
|
||||
const row = [];
|
||||
for (let y = 0; y < img.bitmap.height; y++) {
|
||||
row[y] = intToRGBA(img.getPixelColor(x, y)).b;
|
||||
}
|
||||
vals[x] = row;
|
||||
}
|
||||
|
||||
/* 3. Compute the DCT.
|
||||
* The DCT separates the image into a collection of frequencies
|
||||
* and scalars. While JPEG uses an 8x8 DCT, this algorithm uses
|
||||
* a 32x32 DCT.
|
||||
*/
|
||||
const dctVals = applyDCT(vals, this.size);
|
||||
|
||||
/* 4. Reduce the DCT.
|
||||
* This is the magic step. While the DCT is 32x32, just keep the
|
||||
* top-left 8x8. Those represent the lowest frequencies in the
|
||||
* picture.
|
||||
*/
|
||||
/* 5. Compute the average value.
|
||||
* Like the Average Hash, compute the mean DCT value (using only
|
||||
* the 8x8 DCT low-frequency values and excluding the first term
|
||||
* since the DC coefficient can be significantly different from
|
||||
* the other values and will throw off the average).
|
||||
*/
|
||||
let total = 0;
|
||||
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
total += dctVals[x]![y]!;
|
||||
}
|
||||
}
|
||||
|
||||
const avg = total / (this.smallerSize * this.smallerSize);
|
||||
|
||||
/* 6. Further reduce the DCT.
|
||||
* This is the magic step. Set the 64 hash bits to 0 or 1
|
||||
* depending on whether each of the 64 DCT values is above or
|
||||
* below the average value. The result doesn't tell us the
|
||||
* actual low frequencies; it just tells us the very-rough
|
||||
* relative scale of the frequencies to the mean. The result
|
||||
* will not vary as long as the overall structure of the image
|
||||
* remains the same; this can survive gamma and color histogram
|
||||
* adjustments without a problem.
|
||||
*/
|
||||
let hash = "";
|
||||
|
||||
for (let x = 0; x < this.smallerSize; x++) {
|
||||
for (let y = 0; y < this.smallerSize; y++) {
|
||||
hash += dctVals[x]![y]! > avg ? "1" : "0";
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
// DCT function stolen from http://stackoverflow.com/questions/4240490/problems-with-dct-and-idct-algorithm-in-java
|
||||
|
||||
/**
|
||||
Convert a 32-bit integer color value to an RGBA object.
|
||||
*/
|
||||
function intToRGBA(i: number) {
|
||||
const a = i & 0xff;
|
||||
i >>>= 8;
|
||||
const b = i & 0xff;
|
||||
i >>>= 8;
|
||||
const g = i & 0xff;
|
||||
i >>>= 8;
|
||||
const r = i & 0xff;
|
||||
|
||||
return { r, g, b, a };
|
||||
}
|
||||
|
||||
const c: number[] = [];
|
||||
|
||||
function initCoefficients(size: number) {
|
||||
for (let i = 1; i < size; i++) {
|
||||
c[i] = 1;
|
||||
}
|
||||
|
||||
c[0] = 1 / Math.sqrt(2.0);
|
||||
}
|
||||
|
||||
function applyDCT(f: number[][], size: number) {
|
||||
const N = size;
|
||||
const F: number[][] = [];
|
||||
|
||||
for (let u = 0; u < N; u++) {
|
||||
const row = [];
|
||||
for (let v = 0; v < N; v++) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < N; j++) {
|
||||
sum +=
|
||||
Math.cos(((2 * i + 1) / (2.0 * N)) * u * Math.PI) *
|
||||
Math.cos(((2 * j + 1) / (2.0 * N)) * v * Math.PI) *
|
||||
f[i]![j]!;
|
||||
}
|
||||
}
|
||||
|
||||
sum *= (c[u]! * c[v]!) / 4;
|
||||
row[v] = sum;
|
||||
F[u] = row;
|
||||
}
|
||||
}
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
export default ImagePHash;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "@jimp/config-typescript/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import config from "@jimp/config-vitest/browser";
|
||||
|
||||
export default config;
|
||||
Reference in new issue
Block a user