A dhash implementation for Deno.
A fast algorithm that allows checking if two images are "kind of" the same (the same source image, slightly modified). Examples:
- A resized, compressed, slightly cropped, or color-altered image compared with the original
- A watermarked image versus it's source
- Meme images (mostly the same template, different text)
It does this by computing a perceptual hash of each image and then using it to
compare similarity.
Perceptual hashing is the use of a fingerprinting algorithm that produces a
snippet or fingerprint of various forms of multimedia.
Based on the "Kind of Like That" article by Dr. Neal Krawetz.
Live demo (Deno Deploy): https://dhash.claudiuceia.deno.net/
The demo source lives in docs/ (docs/main.tsx, docs/client.js) and is
deployed separately from the JSR package.
You can compare dhash values by simply computing the Hamming distance between them:
- A distance of 0 represents an identical, or very similar image
- A distance greater than 10 means that you're most likely dealing with a different image
- A distance between 1 and 10 may indicate that you're dealing with variations of the same base image
const [hash1, hash2] = await Promise.all([
dhash("./tests/dalle.png"),
dhash("./tests/dalle-copyright.png"),
]);
console.log(compare(hash1, hash2));Bit convention: this implementation sets bit 1 when the pixel intensity
increases left-to-right (left < right). Use dhash(src, { invert: true }) if
you need the opposite convention to match another implementation.
In addition to dhash() and compare():
toAscii(hash: string, chars?: [string, string]): string
raw(hash: string): Promise<Uint8Array> // PNG bytes for the 8x8 fingerprint
save(hash: string, filePath: string): Promise<void> // writes `${filePath}.png`toAscii() always renders an 8x8 matrix (64 bits); leading zero bits are
preserved.
- Run tests:
deno task test(requires--allow-read --allow-ffi --allow-envbecausesharpuses native bindings and reads fixtures).
MIT © Claudiu Ceia