npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stabilityprotocol.com/phash

v1.0.0

Published

Perceptual hash (pHash) implementation for Node and browser.

Readme

@stabilityprotocol.com/phash

Perceptual hash (pHash) implementation that runs in Node and the browser with no dependencies. Written in TypeScript with full type definitions.

Features

  • 🚀 Zero dependencies - Pure TypeScript/JavaScript implementation
  • 🔧 Type-safe - Full TypeScript support with comprehensive type definitions
  • 🌐 Universal - Works in Node.js and browsers
  • 📦 Multiple formats - ESM and CommonJS builds
  • 🎯 Well-documented - Complete JSDoc documentation for all functions
  • Fast - DCT-based perceptual hashing algorithm

Live Examples

🎨 Try the interactive examples - Upload images and see perceptual hashing in action!

Install

npm install @stabilityprotocol.com/phash

Usage

TypeScript

import phash, { fromRgba, fromImageData, fromImage, fromFile, PhashOptions } from "@stabilityprotocol.com/phash";

// From RGBA buffer with full type safety
const hash: string = fromRgba(rgba, width, height);

// With options
const options: PhashOptions = {
  hashSize: 16,      // 16x16 = 256-bit hash
  sampleSize: 128    // Resize to 128x128 before DCT
};
const customHash = fromRgba(rgba, width, height, options);

// From ImageData
const hashFromImageData: string = fromImageData(imageData);

// From Image element (browser)
const hashFromImage: string = fromImage(imgElement);

// From File (browser, async)
const hashFromFile: Promise<string> = fromFile(file);

// Using default function
const hashViaDefault: string = phash(rgba, width, height);

ESM (browser or Node):

import phash, { fromRgba, fromImageData, fromImage, fromFile } from "@stabilityprotocol.com/phash";

const hash = fromRgba(rgba, width, height);
const hashFromImageData = fromImageData(imageData);
const hashFromImage = fromImage(imgElement);
const hashFromFile = await fromFile(file);

const hashViaDefault = phash(rgba, width, height);

CommonJS (Node):

const phash = require("@stabilityprotocol.com/phash");

const hash = phash.fromRgba(rgba, width, height);

API

  • phash(input, width?, height?, options?)
    • Accepts ImageData-like objects, or RGBA buffers with width and height.
  • fromRgba(rgba, width, height, options?)
  • fromImageData(imageData, options?)
  • fromImage(image, options?) (browser-only unless you provide a canvas implementation)
  • fromFile(file, options?) (browser-only)
  • algorithms.universal.* access to the current algorithm implementation.

Options

All hashing functions accept an optional options parameter:

interface PhashOptions {
  hashSize?: number;      // Size of hash in bits per dimension (default: 8 for 64-bit hash)
  sampleSize?: number;    // Size to resize image before DCT (default: 64)
  createCanvas?: (width: number, height: number) => HTMLCanvasElement | OffscreenCanvas;
}
  • hashSize (default: 8) - Controls the hash dimensions. 8 = 8×8 = 64-bit hash, 16 = 16×16 = 256-bit hash
  • sampleSize (default: 64) - Image is resized to this size before computing DCT
  • createCanvas(width, height) - Custom canvas factory for environments without DOM or OffscreenCanvas

Development

# Install dependencies
npm install

# Build the library (uses tsup)
npm run build

# Run tests
npm test

# Serve examples locally
npx serve examples

Release Process

This project uses semantic-release for fully automated versioning and npm publishing.

How It Works

When commits are pushed to the main branch, semantic-release automatically:

  1. Analyzes commit messages to determine version bump
  2. Generates release notes and updates CHANGELOG.md
  3. Updates package.json version
  4. Publishes to npmjs.com
  5. Creates a GitHub Release with generated notes
  6. Commits the version bump back to the repository

Commit Message Convention

Follow Conventional Commits format:

| Type | Version Bump | Example | |------|--------------|---------| | fix: | Patch (0.0.X) | fix: resolve edge case in hash calculation | | feat: | Minor (0.X.0) | feat: add support for WebP images | | feat!: or BREAKING CHANGE: | Major (X.0.0) | feat!: change API signature | | docs:, chore:, style:, refactor:, test: | No release | chore: update dependencies |

Examples

# Patch release (0.1.0 → 0.1.1)
git commit -m "fix: correct hash comparison logic"

# Minor release (0.1.1 → 0.2.0)
git commit -m "feat: add grayscale conversion options"

# Major release (0.2.0 → 1.0.0)
git commit -m "feat!: redesign public API

BREAKING CHANGE: fromRgba now requires options parameter"

Manual Release

No manual steps needed! Just push to main with properly formatted commits and semantic-release handles the rest.

How It Works

The perceptual hash algorithm:

  1. Resize - Scale image to a square (default 64×64) using bilinear interpolation
  2. Grayscale - Convert to grayscale using luminosity method (ITU-R BT.601)
  3. DCT - Apply 2D Discrete Cosine Transform to extract frequency components
  4. Reduce - Extract top-left DCT coefficients (default 8×8) containing low-frequency data
  5. Threshold - Compute median of DCT values (excluding DC component)
  6. Hash - Create binary hash where each bit = 1 if value > median, else 0
  7. Encode - Convert binary to hexadecimal string

Similar images produce similar hashes because they share low-frequency visual patterns.

License

MIT