npm package: @stabilityprotocol.com/phash
Description: Perceptual hash (pHash) implementation for Node and browser.
Latest version: 1.0.0

# @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](https://stabilityprotocol.github.io/monolith-phash-algo/)** - Upload images and see perceptual hashing in action!

## Install

```bash
npm install @stabilityprotocol.com/phash
```

## Usage

### TypeScript

```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):

```js
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):

```js
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:

```typescript
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

```bash
# 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](https://github.com/semantic-release/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](https://www.conventionalcommits.org/) 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

```bash
# 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