Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Imagehash Laravel Package

jenssegers/imagehash

Perceptual image hashing for PHP and Laravel. Generate hashes to detect duplicate images and find visually similar pictures using aHash, dHash, pHash and more. Works with Intervention Image in any PHP project. Fast, lightweight, and great for deduplication and content moderation.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

A feature you can ship next sprint instead of next quarter. Perceptual hashing turns "duplicate image detection" — a line item that usually gets parked behind "we need an ML team" — into a queue job and a column. The package (jenssegers/imagehash, MIT, ~2.1k stars, actively released) is pure PHP, installs via Composer, and runs in-process: no Python service, no vector database, no cloud vision contract, no vendor DPA, no per-image API spend, no user media leaving the app.

  • Duplicate / near-duplicate upload detection. "You've already added this image" for marketplaces, classifieds, real estate listings, CMS media libraries, and UGC feeds. Works on resized, re-compressed, and lightly edited copies — the actual failure mode of an exact-hash or filename check.
  • Media library hygiene and consolidation. Backfill hashes across existing assets, surface redundant groups, let content ops merge or prune. This is the rare roadmap item whose savings (storage + cleanup toil) land in the same quarter you build it.
  • Lightweight "similar images" discovery. A credibility feature on search results and product detail pages that needs no embeddings infrastructure and no new on-call owner.
  • Fraud and abuse triage. Recycled listing photos are a common scam pattern. Match new uploads against a curated corpus and route hits to human review — never auto-block. The cost of a wrong auto-block is far higher than the cost of a review queue.
  • Build vs. buy: this is the "buy" that behaves like a build. It displaces a cloud vision contract or an internal ML microservice for the perceptual-hashing slice only. It does not displace anything for classification, OCR, or semantic search.
  • Architecture optionality, cheaply. Put an internal ImageSimilarity interface in front of it (hash → string, distance → int). Swapping to a managed service later becomes a container binding change, not a rewrite. That is the single most defensible reason to approve it.

The decision this package hands back to you — deliberately. The library returns a distance number; the cutoffs are product policy. Commit explicitly to two tiers in config: "duplicate" (merge, block, or badge) and "similar" (nudge or suggest). Thresholds are domain-specific — product photography, screenshots, and scanned documents are three different numbers — so tuning is a product-policy exercise with a real spike (a few hundred real assets, a distance histogram, a hand-reviewed sample), not a library setting you copy from a blog post.

Explicitly out of scope — say it in the kickoff or scope will creep: object detection, face recognition, OCR, captioning, NSFW classification, semantic search, and rotation invariance. If a stakeholder's mental model of "image AI" includes any of those, name the gap on day one.

Sequencing that keeps you out of trouble: schema → backfill command → offline images:duplicates report → hand-review the report → advisory badge in UI → feature-flagged merge with manual override. Ship dedupe dark first. Systematic false positives (solid colours, gradients, heavy letterboxing, watermarks) are the real UX risk, and you want the audit trail of which pair triggered a merge before anyone can trigger one.

Success metrics worth defining up front: duplicate groups surfaced per 1,000 uploads, review-queue precision from the hand-reviewed sample, storage reclaimed from consolidation, and the observed distance distribution over the first few weeks of production.

When to Consider This Package

Adopt when:

  • The product surface is already PHP/Laravel and you don't want to operate a second runtime for one capability.
  • The requirement is perceptual similarity — "is this the same or a visually near-identical image?" — not "what is in this image?"
  • Volume is moderate and hashing can run asynchronously on existing queue workers. It's CPU-bound but cheap per image (tens of milliseconds).
  • GD or Imagick is present in every runtime — web FPM, Horizon workers, Octane containers, CI. This, not the package, is the real prerequisite; Class "Imagick" not found on the worker is the classic day-one failure. Pick one driver and pin it everywhere (Dockerfile + composer.json config.platform), because GD and Imagick decode edge cases slightly differently and can shift a hash by a bit or two.
  • Licensing and dependency footprint need to clear legal and security review fast. MIT plus a small tree does that.
  • You accept ownership of the two things the package intentionally leaves to you: threshold tuning and hash storage plus a lookup strategy (a column, a banded index, a backfill job, a hash_version).

Look elsewhere when:

  • You need classification, moderation verdicts, OCR, faces, or semantic search. Hashing answers none of these.
  • Rotation invariance is a hard requirement. dHash and pHash are not rotation-invariant, and EXIF orientation handling depends on the decoder. Decide explicitly whether a rotated photo counts as a duplicate — if yes, this package alone won't get you there.
  • Your catalogue is large and you expect sub-100ms lookups at scale. 64-bit Hamming distance has no B-tree story; past roughly 10k assets you'll need banding (split the hex into four chunks, index those) or a real ANN store. Plan for it, don't discover it.
  • You need pixel-perfect identity only. A cryptographic hash plus a unique index is simpler and exact.
  • Your images are large-source heavy and you can't guarantee a downscale step. A 6000×4000 JPEG decodes to ~100 MB; GD memory exhaustion is the most likely production incident here. Mitigate before adopting: resize to ~256×256 before hashing and cap dimensions in the FormRequest.
  • Nobody will own the tuning. Without someone reviewing a distance histogram against real assets, you get silent false merges — the worst kind of bug, because users notice and nobody can explain it.

Two operational commitments that come with adoption — treat these as part of the cost, not optional polish: (1) fail open on decode errors (corrupt files, CMYK JPEGs, animated GIFs, HEIC, 0-byte uploads) so the similarity check is never the reason an upload fails; (2) version your hashes, because a GD/Imagick/intervention/image bump can silently shift hashes and make old and new rows incomparable. hash_version is how you detect that and turn a data-loss event into a backfill.

One dependency to watch: the package wraps intervention/image, so its major-version bumps are your real upgrade risk, not this package's small public API. Pin the imagehash version explicitly.

How to Pitch It (Stakeholders)

One line: We can ship duplicate and near-duplicate image detection next sprint using an MIT-licensed PHP library that runs inside our existing app — no new service, no vendor contract, no per-image fees, and no user media leaving our infrastructure.

For executives. This replaces a "needs an ML team" roadmap item with a one-sprint spike plus a queue job, and frees ML capacity for genuinely hard problems rather than a well-understood primitive. Costs: an engineer-sprint to spike and integrate, plus one for the backfill and review tooling. There's no procurement cycle, no recurring API spend, and no data-processing agreement to negotiate — it's a Composer install. The measurable returns are concrete: storage reclaimed from consolidating redundant assets, manual cleanup toil removed from content ops, and a fraud signal (recycled listing photos) routed to human review instead of paying out on bad listings. The risk is bounded and reversible: an internal interface keeps the similarity primitive swappable for a managed service later, so the exit cost is a container binding, not a rewrite.

For engineering. It's a small, actively maintained, MIT library with a tiny public API: hash(), distance(), compare(), plus four algorithms — DifferenceHash (default, 64-bit), PerceptualHash (more robust to re-encoding/resizing, slower), AverageHash (fastest, least accurate), BlockHash (256-bit). Start with dHash; move to pHash only if the spike shows re-encoded or resized copies slipping past threshold. Bind it once behind our own ImageSimilarity interface — never instantiate it in a controller — so the algorithm choice lives in one place. Store hex, not bits, in a char(16) column (or char(64) for BlockHash — the wrong size truncates silently), alongside hash_algorithm and hash_version. Hash in a queued, idempotent, ShouldBeUnique job off the request path. Never call compare() in production — it decodes both files every time; store hashes and use distance(). Handle S3 by streaming to a temp file or building an in-memory image. Past ~10k assets, add a banded index as a cheap prefilter. Test against 8–10 fixture files (original, resized, re-encoded, screenshot, solid colour, two genuinely different photos) and assert distance ranges, not exact hashes — exact-hash assertions break on a GD bump. And don't hash user-supplied URLs; "paste an image link" is an SSRF vector.

What we are explicitly not promising. This is not image classification, moderation verdicts, OCR, face recognition, or semantic search, and it is not rotation-invariant. It tells us two images look alike. Everything about what to do when they do — thresholds, merge rules, review routing, overrides — is a product decision we own, which is precisely why it should be explicit in config and revisited with real data rather than buried in a magic number.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib