phash_native

A minimal, native, zero-dependency Ruby extension for computing perceptual hashes (pHash) from image files. Built entirely in C using stb_image.h, with no external dependencies outside the standard C library. Fast, simple, and does exactly one thing right.

Why this exists

There are existing Ruby gems that attempt to do perceptual hashing (like phashion), but:

  • They're old and abandonware.
  • They rely on broken or outdated C++ libraries.
  • They fail to compile on modern systems.
  • They use external dependencies like FFTW or libjpeg, and end up being fragile and drifting out of compatibility over time.

I needed something that worked. Something that could:

  • Read an image.
  • Compute a stable 64-bit perceptual hash based on DCT.
  • Compare hashes efficiently with Hamming distance.
  • Compile without screwing around with a million packages.

So I wrote it.

Installation

gem install phash_native

Or in your Gemfile:

gem "phash_native"

Usage

require "phash_native"

hash = PhashNative.compute("some/image.png")
# => 64-bit integer, e.g. 0x4f393c7331c7e7cc

# Compare two images
a = PhashNative.compute("image1.png")
b = PhashNative.compute("image2.png")
PhashNative.hamming(a, b)
# => integer between 0 and 64

Interpreting results

The closer two hashes are (i.e. the smaller the Hamming distance), the more visually similar the images are. A Hamming distance of 0 means they're identical in structure. Under 10 is usually a strong match. Over 20? Probably different content.

Performance

The native code uses:

  • A real 2D DCT on a 32×32 grayscale sample
  • A simple median threshold over the top-left 8×8 DCT block
  • Fast bitwise Hamming comparison (utilizes GCC intrinsics if available)

This means it runs fast — fast enough for batch processing thousands of frames without sweating.

Limitations

  • Only supports images readable by stb_image.h (which covers PNG, JPEG, BMP, etc.) But what more could you need?
  • Always converts to grayscale and downscales to 32×32 internally
  • No audio or video support — this is just for still images
  • No SIMD or threading — yet. PRs welcome.

Yes, you could write your own. But now you don’t have to.