diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..db6323f --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +//default.npmjs.org/:_authToken=${NPM_TOKEN} \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index 128312c..0000000 --- a/index.js +++ /dev/null @@ -1,19 +0,0 @@ -const { download, hash, calculateSimilarity } = require("./lib"); - -const URL1 = - "https://res.cloudinary.com/demo/image/upload/f_auto,q_auto/w_400/koala1.jpg"; -const URL2 = "https://res.cloudinary.com/demo/image/upload/h_180/koala2.jpg"; -const URL3 = "https://res.cloudinary.com/demo/image/upload/h_180/koala4.jpg"; - -async function main() { - console.log("Urls", { URL1, URL3 }); - const image1 = await download(URL1); - const image2 = await download(URL3); - const hash1 = await hash(image1); - const hash2 = await hash(image2); - console.log("Hashes", { hash1, hash2 }); - const similarity = calculateSimilarity(hash1, hash2); - console.log("similarity", { similarity }); -} - -main().catch((err) => console.log(err)); diff --git a/package-lock.json b/package-lock.json index 15347fd..cfc5c58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "phash-test", - "version": "1.0.0", + "name": "image-phash", + "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "phash-test", - "version": "1.0.0", - "license": "ISC", + "name": "image-phash", + "version": "0.1.0", + "license": "MIT", "dependencies": { "@canvas/image": "^1.0.1", "axios": "^0.26.1", diff --git a/package.json b/package.json index d609e54..5dc13cf 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { - "name": "phash-test", - "version": "1.0.0", + "name": "image-phash", + "version": "0.1.0", "description": "", - "main": "index.js", - "scripts": { - "start": "node index.js" - }, - "keywords": [], - "author": "", - "license": "ISC", + "main": "./src/lib.js", + "keywords": [ + "javascript", + "phash", + "hashing", + "images" + ], + "author": "Victor Martinez ", + "license": "MIT", "dependencies": { "@canvas/image": "^1.0.1", "axios": "^0.26.1", @@ -16,5 +18,13 @@ }, "devDependencies": { "@types/node": "^17.0.21" - } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/JasterV/hash-image.git" + }, + "bugs": { + "url": "https://github.com/JasterV/hash-image/issues" + }, + "homepage": "https://github.com/JasterV/hash-image#readme" } \ No newline at end of file diff --git a/src/lib.js b/src/lib.js new file mode 100644 index 0000000..53e7d2c --- /dev/null +++ b/src/lib.js @@ -0,0 +1,43 @@ +const blockhash = require("blockhash-core"); +const { getImageData, imageFromBuffer } = require("@canvas/image"); +const { hexToBin, download } = require("./utils"); + +class HashImage { + constructor(buffer) { + if (!(buffer instanceof Uint8Array)) { + throw new Error( + "Invalid parameter, please use a buffer or an instance of Uint8Array" + ); + } + this.buffer = buffer; + } + + static async fromUrl(url) { + const buffer = await download(url); + return new HashImage(buffer); + } + + static hashCompare(hash1, hash2) { + let similarity = 0; + const hash1Array = hash1.split(""); + hash1Array.forEach((bit, index) => { + hash2[index] === bit ? similarity++ : null; + }); + return similarity / hash1.length; + } + + async hash() { + const data = await imageFromBuffer(this.buffer); + const hexHash = await blockhash.bmvbhash(getImageData(data), 8); + const hash = hexToBin(hexHash); + return hash; + } + + async compare(other) { + const hash1 = await this.hash(); + const hash2 = await other.hash(); + return HashImage.hashCompare(hash1, hash2); + } +} + +module.exports = { HashImage }; diff --git a/lib.js b/src/utils/index.js similarity index 72% rename from lib.js rename to src/utils/index.js index 949a5ad..1c5f8dd 100644 --- a/lib.js +++ b/src/utils/index.js @@ -1,13 +1,6 @@ -const blockhash = require("blockhash-core"); -const { getImageData, imageFromBuffer } = require("@canvas/image"); -const axios = require("axios").default; - -async function hash(buffer) { - const image = await imageFromBuffer(buffer); - const hash = await blockhash.bmvbhash(getImageData(image), 8); - return hexToBin(hash); -} +const { default: axios } = require("axios"); +// Utils async function download(url) { const response = await axios.get(url, { responseType: "stream" }); const stream = response.data; @@ -19,7 +12,7 @@ async function download(url) { return buffer; } -function calculateSimilarity(hash1, hash2) { +function calculateHashSimilarity(hash1, hash2) { let similarity = 0; const hash1Array = hash1.split(""); hash1Array.forEach((bit, index) => { @@ -61,7 +54,7 @@ function hexToBin(hexString) { } module.exports = { - hash, download, - calculateSimilarity, + hexToBin, + calculateHashSimilarity, };