Skip to content

Commit 983a62e

Browse files
committed
docs: document public api
1 parent 2bf13b2 commit 983a62e

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

src/dhash.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import sharp from "sharp";
22
import { normalize, resolve } from "@std/path";
33

4+
/**
5+
* Options for {@link dhash}.
6+
*/
47
export type DHashOptions = {
58
/**
69
* Flip the bit convention for left/right comparisons.
@@ -13,11 +16,29 @@ export type DHashOptions = {
1316

1417
const MASK_64 = (1n << 64n) - 1n;
1518

19+
/**
20+
* Invert a 64-bit dHash (bitwise NOT), preserving leading zeroes.
21+
*
22+
* This is useful when matching the opposite bit convention used by other
23+
* implementations.
24+
*/
1625
export const invertHash = (hash: string): string => {
1726
const v = BigInt("0x" + hash);
1827
return ((~v) & MASK_64).toString(16).padStart(16, "0");
1928
};
2029

30+
/**
31+
* Compute the 64-bit difference hash (dHash) for an image.
32+
*
33+
* Algorithm: grayscale -> resize to 9x8 -> compare adjacent pixels left-to-right
34+
* to produce 64 bits -> return as 16-char hex string.
35+
*
36+
* Bit convention: by default, bit `1` means the intensity increases left-to-right
37+
* (`left < right`). Use `options.invert` to flip this.
38+
*
39+
* @param pathOrSrc File path (relative to `Deno.cwd()`) or raw image bytes.
40+
* @returns 16-character lowercase hex string.
41+
*/
2142
export const dhash = async (
2243
pathOrSrc: string | Uint8Array,
2344
options: DHashOptions = {},
@@ -51,6 +72,11 @@ export const dhash = async (
5172
.padStart(16, "0");
5273
};
5374

75+
/**
76+
* Compare two hex hashes by computing the Hamming distance.
77+
*
78+
* Lower is more similar, higher is more different.
79+
*/
5480
export const compare = (hash1: string, hash2: string): number => {
5581
if (hash1.length !== hash2.length) {
5682
throw new Error(`
@@ -65,6 +91,12 @@ export const compare = (hash1: string, hash2: string): number => {
6591
return xor.toString(2).split("1").length - 1;
6692
};
6793

94+
/**
95+
* Render a hash as an 8x8 ASCII/Unicode fingerprint.
96+
*
97+
* Always renders 64 bits (leading zeros preserved). Customize the output by
98+
* changing the "off/on" character pair via `chars`.
99+
*/
68100
export const toAscii = (hash: string, chars = ["░░", "██"]): string => {
69101
// Use BigInt to avoid precision loss; always render 64 bits (8x8).
70102
const bin = BigInt("0x" + hash).toString(2).padStart(64, "0");
@@ -78,6 +110,9 @@ export const toAscii = (hash: string, chars = ["░░", "██"]): string => {
78110
return out;
79111
};
80112

113+
/**
114+
* Convert a hash into an 8x8 PNG (returned as bytes).
115+
*/
81116
export async function raw(hash: string): Promise<Uint8Array> {
82117
const bin = BigInt("0x" + hash).toString(2).padStart(64, "0");
83118

@@ -94,6 +129,11 @@ export async function raw(hash: string): Promise<Uint8Array> {
94129
return await image.png().toBuffer();
95130
}
96131

132+
/**
133+
* Save an 8x8 PNG fingerprint for a hash to disk.
134+
*
135+
* Note: `.png` is appended to `filePath`.
136+
*/
97137
export async function save(hash: string, filePath: string): Promise<void> {
98138
const buffer = await raw(hash);
99139
await Deno.writeFile(`${filePath}.png`, buffer);

0 commit comments

Comments
 (0)