🌄 Perceptual image hashing for PHP

Overview

ImageHash

Latest Stable Version Build Status Coverage Status Donate

A perceptual hash is a fingerprint of a multimedia file derived from various features from its content. Unlike cryptographic hash functions which rely on the avalanche effect of small changes in input leading to drastic changes in the output, perceptual hashes are "close" to one another if the features are similar.

Perceptual hashes are a different concept compared to cryptographic hash functions like MD5 and SHA1. With cryptographic hashes, the hash values are random. The data used to generate the hash acts like a random seed, so the same data will generate the same result, but different data will create different results. Comparing two SHA1 hash values really only tells you two things. If the hashes are different, then the data is different. And if the hashes are the same, then the data is likely the same. In contrast, perceptual hashes can be compared -- giving you a sense of similarity between the two data sets.

This code was inspired/based on:

Requirements

  • PHP 7.1 or higher
  • The gd or imagick extension
  • Optionally, install the GMP extension for faster fingerprint comparisons

Installation

This package has not reached a stable version yet, backwards compatibility may be broken between 0.x releases. Make sure to lock your version if you intend to use this in production!

Install using composer:

composer require jenssegers/imagehash

Usage

The library comes with 4 built-in hashing implementations:

  • Jenssegers\ImageHash\Implementations\AverageHash - Hash based the average image color
  • Jenssegers\ImageHash\Implementations\DifferenceHash - Hash based on the previous pixel
  • Jenssegers\ImageHash\Implementations\BlockHash - Hash based on blockhash.io Still under development
  • Jenssegers\ImageHash\Implementations\PerceptualHash - The original pHash Still under development

Choose one of these implementations. If you don't know which one to use, try the DifferenceHash implementation. Some implementations allow some configuration, be sure to check the constructor.

use Jenssegers\ImageHash\ImageHash;
use Jenssegers\ImageHash\Implementations\DifferenceHash;

$hasher = new ImageHash(new DifferenceHash());
$hash = $hasher->hash('path/to/image.jpg');

echo $hash;
// or
echo $hash->toHex();

The resulting Hash object, is a hexadecimal image fingerprint that can be stored in your database once calculated. The hamming distance is used to compare two image fingerprints for similarities. Low distance values will indicate that the images are similar or the same, high distance values indicate that the images are different. Use the following method to detect if images are similar or not:

$distance = $hasher->distance($hash1, $hash2);
// or
$distance = $hash1->distance($hash2);

Equal images will not always have a distance of 0, so you will need to decide at which distance you will evaluate images as equal. For the image set that I tested, a max distance of 5 was acceptable. But this will depend on the implementation, the images and the number of images. For example; when comparing a small set of images, a lower maximum distances should be acceptable as the chances of false positives are quite low. If however you are comparing a large amount of images, 5 might already be too much.

The Hash object can return the internal binary hash in a couple of different format:

echo $hash->toHex(); // 7878787c7c707c3c
echo $hash->toBin(); // 0111100001111000011110000111110001111100011100000111110000111100
echo $hash->toInt(); // 8680820757815655484
echo $hash->toBytes(); // "\x0F\x07ƒƒ\x03\x0F\x07\x00"

Choose your preference for storing your hashes in your database. If you want to reconstruct a Hash object from a previous calculated value, use:

$hash = Hash::fromHex('7878787c7c707c3c');
$hash = Hash::fromBin('0111100001111000011110000111110001111100011100000111110000111100');
$hash = Hash::fromInt('8680820757815655484');

Demo

These images are similar:

Equals1 Equals2

Image 1 hash: 3c3e0e1a3a1e1e1e (0011110000111110000011100001101000111010000111100001111000011110)
Image 2 hash: 3c3e0e3e3e1e1e1e (0011110000111110000011100011111000111110000111100001111000011110)
Hamming distance: 3

These images are different:

Equals1 Equals2

Image 1 hash: 69684858535b7575 (0010100010101000101010001010100010101011001010110101011100110111)
Image 2 hash: e1e1e2a7bbaf6faf (0111000011110000111100101101001101011011011101010011010101001111)
Hamming distance: 32

Security contact information

To report a security vulnerability, follow these steps.

Comments
  • installation errors at UBUNTU 16

    installation errors at UBUNTU 16

    on composer require jenssegers/imagehash the first problem, that need some FAQ was

    file_put_contents(/home/peter/.composer/cache/repo/https---packagist.org/p-provider-2016-10.json): failed to open stream: Permission denied
    http://packagist.org could not be fully loaded, package information was loaded from the local cache and may be out of date
    

    Them, suppose fix by (not recommended) sudo ... Ok, no permission error, but a new error:

    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Installation request for jenssegers/imagehash dev-master -> satisfiable by jenssegers/imagehash[dev-master].
        - Can only install one of: jenssegers/imagehash[v0.4.1, dev-master].
        - Installation request for jenssegers/imagehash ^0.4.1 -> satisfiable by jenssegers/imagehash[v0.4.1].
    
    
    Installation failed, reverting ./composer.json to its original content.
    
    opened by ppKrauss 8
  • Round up the hash value

    Round up the hash value

    Hello,

    Great class you created and great job done. As for sure you already studied the question, maybe you can suggest the best way to accomplish the following:

    I need to find a duplicates of images in the database and it is not really good idea to compare 2 images one by one...so I came up with the idea - basically what I want to do is to round a Hash result a little and store it for each image in DB...and later just find duplicated values of Hash. I do understand that the result of this solution will not be comparable to the result I get when calculating the hamming distance, but it is ok for me - I just need to find images that are with 95+% probability are duplicated... So, the question is - what is the best place of code to round the Hash? I tried to do it in ImageHash.php, but something goes wrong:

    $hash = round($hash/10)*10;
    return $hash;
    

    returns some stupid results like 9.23423423423E+34

    Any idea what am I doing wrong?

    Thank you in advance!!!

    opened by popovae 8
  • Why returns hex hash in last version?

    Why returns hex hash in last version?

    In previous version method ImageHash->hash() returns an integer? Now it hex value in type "string". I have database of hashes in BIGINT type, and search in integer field is faster than string.

    opened by memboc 7
  • Library does not support php 8.0.1

    Library does not support php 8.0.1

    I got this error when trying to use composer for updating

    - Root composer.json requires jenssegers/imagehash ^0.7.0 -> satisfiable by
    

    jenssegers/imagehash[v0.7.0]. - jenssegers/imagehash v0.7.0 requires php ^7.0 -> your php version (8.0.1 does not satisfy that requirement.

    opened by mitmelon 3
  • class not found error

    class not found error

    Please help.I run in local this package but i getting Fatal error: Class 'Jenssegers\ImageHash\Implementations\DifferenceHash' not found in /opt/lampp/htdocs/demo/imagehash-master/src/ImageHash.php on line 26

    why I getting this error ?Please give answer.

    opened by php1webmobtech 3
  • Storing Hash metadata along the hashes to enable forward-compatibility & rehashing

    Storing Hash metadata along the hashes to enable forward-compatibility & rehashing

    Hi, First of all, thanks for your recent activity, you're upgrading this so fast !

    I was thinking that maybe an implementation akin to php's password_hash, password_verify, password_needs_rehash for perceptual hashes would be great.

    Maybe you'll want, in x years, to migrate to 128*128 sources for the hashes, or to 256bit hashes, as hardware gains in processing power.. Or you'd like to compensate for switching from an image processing backend to another, and anticipate slightly different hashes.

    Maybe along hashes could be stored backend type, sample size, and hash length information, to allow for smarter compare functions ?

    The main use case would be something along those lines :

    • Given a picture, hashed on 2017/01/01, with gd, a 32x32 source, to a 64bit hash
    • Given you now hash with imagemagick, a 128x128 source, to a 256bit hash because you found it provides stellar results - this is pure speculation -
    • Given you trigger a massive search for potential duplicates in your database

    While walking the database, each hash is compared to today's default implementation. If its hash is obsolete, you can re-hash it instantly and move on with your comparisons.

    I'd be willing to work on this if it seems useful enough. The drawbacks resides in a nonstandard perceptual hash storage, but I doubt there are standards on this matter right now.

    Have a nice day !

    opened by Lucassifoni 2
  • Update for php 8, phpunit 9 and switch to github actions

    Update for php 8, phpunit 9 and switch to github actions

    This revealed a few existing issues with the imagemagick backend, not quite sure yet how to fix those. Also, you might want to export the styleCI configuration as a .styleci.yml file, so that contributors like me can help fix the failing styleCI tasks :)

    opened by danog 1
  • Explicit MIT license.

    Explicit MIT license.

    This is an explicit MIT license, based on issue #1

    The text comes from https://opensource.org/licenses/MIT

    The copyright years are based on git history.

    opened by myrkraverk 1
  • Greyscale the image when using DifferenceHash

    Greyscale the image when using DifferenceHash

    As described in http://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html, a "reduction of color" is recommended. ("For optimal performance, either reduce color before scaling or perform the scaling and color reduction at the same time."). Also, I reused the $image object for a bit of memory optimization.

    opened by bogdanstoik 1
  • question

    question

    great library, need to say that first.

    Scenario: If we have a large library of pictures, we can calculate and store the ahash, dhash and phash in an mysql table. Then, for any new picture, we can calculate the hash, but in order to see if we already have something similar in the db, we need to calculate the distance between the new pic and each of the hashes stored in the db. Is there any way to translate the comparison function to a mysql function, so that we would "select" the values in the db that are near the hash we are checking?

    opened by rlucian 1
  • Unclosed resources?

    Unclosed resources?

    If you hash an image by filename the hash function will create a resource that is never closed.

    https://github.com/jenssegers/php-imagehash/blob/master/src/ImageHash.php#L36

    public function hash($resource)
    {
        $resource = is_resource($resource) ? $resource : $this->loadImageResource($resource);
        $hash = $this->implementation->hash($resource);
        return $hash;
    }
    
    opened by i124q2n8 1
  • Undocumented breaking change due to type hints

    Undocumented breaking change due to type hints

    We're updating to latest version and have noticed a breaking change when using:

    Hash::fromInt($num);
    

    This use to allow strings, nulls and even super large integers - but now it seems restricted to int type due to this commit:

    https://github.com/jenssegers/imagehash/compare/v0.6.0...v0.7.0

    PHP int value is limited in size, so when we try to use it from values using BIGINT from mysql it no longer works - mysql will return BIGINT values as strings in PHP because they cannot be used as native ints. That's the whole purpose of the BIGINT library, right?

    E.g. this is a BIGINT of a difference hash for one of our pictures in our database and it doesn't fit as an int.

    echo (int)'10957988095268482955'
    

    fromInt shouldn't typehint int because it's whole purpose is to support big ints.

    opened by garygreen 0
  • Same result for different images

    Same result for different images

    I really like this library. But I need some improvement. Like in this example. The hash is the same, but the images are different. I need more accuracy and certainty that the pictures are the same.

    How to do it? Snímek obrazovky 2022-06-26 v 15 18 32

    opened by cogniti75 0
  • Hash size

    Hash size

    Fabulous work, thanks.

    I see the examples have different hash lenght. Is the hash length corresponds to the image dimensions? I believe the hash represents the image details. Can we specify the sensitivity (for example with changing the hash length to 512 byte)?

    Thanks.

    opened by omidMolaverdi 3
  • BUG : Uncaught Error: Call to a member function toHex() on string

    BUG : Uncaught Error: Call to a member function toHex() on string

    It seems you had another update on the library but didnt updated the documentation..

    On using toHex():

    PHP Fatal error: Uncaught Error: Call to a member function toHex() on string in..

    What is the best method of conversion?

    opened by mitmelon 0
  • BUG : Uncaught Error: Call to a member function toHex() on string

    BUG : Uncaught Error: Call to a member function toHex() on string

    It seems you had another update on the library but didnt updated the documentation..

    On using toHex():

    PHP Fatal error: Uncaught Error: Call to a member function toHex() on string in..

    What is the best method of conversion?

    opened by mitmelon 1
Releases(v0.8.0)
Owner
Jens Segers
Head of Engineering at CHEQROOM
Jens Segers
Auto Image & file upload, resize and crop for Laravel eloquent model using Intervention image

Laravel ImageUp The qcod/laravel-imageup is a trait which gives you auto upload, resize and crop for image feature with tons of customization. Install

QCode.in 708 Dec 22, 2022
A Laravel Gravatar package for retrieving gravatar image URLs or checking the existance of an image.

Gravatar for Laravel 5.x, 6, 7 and 8 Installation First, pull in the package through Composer via the command line: composer require creativeorange/gr

Creativeorange 477 Dec 1, 2022
This plugin adds a new image style for the Core Image block.

This plugin adds a new image style for the Core Image block. Introduction How to use? Go to Gutenberg Editor and add a image block. e.g. Add new image

Mahesh Waghmare 3 Feb 17, 2022
PHP Image Manipulation

Intervention Image Intervention Image is a PHP image handling and manipulation library providing an easier and expressive way to create, edit, and com

null 13k Jan 3, 2023
PHP 5.3 Object Oriented image manipulation library

Imagine Tweet about it using the #php_imagine hashtag. Image manipulation library for PHP 5.3 inspired by Python's PIL and other image libraries. Requ

Bulat Shakirzyanov 4.3k Jan 6, 2023
php-gd based image templates

gdaisy A highly experimental image templating system based on PHP-GD to dynamically generate image banners and covers. Installation 1. Require erikahe

Erika Heidi 67 Nov 22, 2022
Grabs the dominant color or a representative color palette from an image. Uses PHP and GD, Imagick or Gmagick.

Color Thief PHP A PHP class for grabbing the color palette from an image. Uses PHP and GD or Imagick libraries to make it happen. It's a PHP port of t

Kevin Subileau 610 Dec 28, 2022
PHP library to easily edit image with GD extension. Resize, crop, merge, draw, and many more options !

PHP Image Editor PHP library to easily edit image with GD extension. Resize, crop, merge, draw, and many more options ! ✨ Supporting ⭐ Star this repos

Franck Alary 17 Nov 13, 2022
image sharing site made in PHP just for fun and freetime

2bart image sharing site made in PHP just for fun and freetime To-do list: upload system [DONE] ✔️ views system [DONE] ✔️ image list system [DONE] ✔️

goom 1 Oct 22, 2021
This is an image manipulation REST API written in PHP Laravel Framework

Laravel Image Manipulation REST API Demo Here is fully working Demo: https://www.lobiimages.com/ You have to register first in order to generate acces

TheCodeholic 42 Dec 15, 2022
PHP Thumb is a light-weight image manipulation library aimed at thumbnail generation

PHP Thumb NOTICE - This project was recently updated to 2.0 and is PSR-0 compliant and supports Composer integration. Some parts of the documentation

Ian Selby 985 Dec 4, 2022
Image manager extension for the Yii PHP framework.

yii-imagemanager Image manager extension for the Yii PHP framework. Introduction I started this project to reduce the need for boilerplate code when w

Christoffer Niska 23 Aug 28, 2020
Wonderfully easy on-demand image manipulation library with an HTTP based API.

Glide Glide is a wonderfully easy on-demand image manipulation library written in PHP. Its straightforward API is exposed via HTTP, similar to cloud i

The League of Extraordinary Packages 2.4k Dec 19, 2022
Image optimization / compression library. This library is able to optimize png, jpg and gif files in very easy and handy way. It uses optipng, pngquant, pngcrush, pngout, gifsicle, jpegoptim and jpegtran tools.

Image Optimizer This library is handy and very easy to use optimizer for image files. It uses optipng, pngquant, jpegoptim, svgo and few more librarie

Piotr Śliwa 879 Dec 30, 2022
:racehorse: find the size of an image without downloading the whole file. Supports batch requests.

FasterImage FasterImage finds the dimensions or filetype of a remote image file given its uri by fetching as little as needed, based on the excellent

Will Washburn 58 Nov 30, 2022
Extract colors from an image like a human would do.

ColorExtractor Extract colors from an image like a human would do. Install Via Composer $ composer require league/color-extractor:0.3.* Usage require

The League of Extraordinary Packages 1.2k Jan 1, 2023
An open source image hosting service powered by Laravel

Limg An open source image hosting service powered by Laravel Features Upload your image via file, url or ShareX ! Manage your image (custom title, pub

Thomas 56 Dec 16, 2022
A simple page view counter that store data as text and shows data as a PNG image

Image Counter A simple page view counter that store data as text and shows the counter as a PNG image.

Victor Ribeiro 10 Apr 19, 2022
Convert image types. Take samples of pdfs or psd, do some filters as SEPIA, resizes. Save to WEBP

img2img. PHP Converter, sampler of pdfs & psd, do resizes & some filters in images as SEPIA. Save to WEBP V.1.0.3 This class in pure PHP try to manage

Rafael Martin Soto 9 Oct 23, 2022