← Back to blog

dHash: The Gradient‑Based Duplicate Finder for Exposure‑Corrected Images

Sakarto's dHash (Difference Hash) algorithm finds duplicate photos and videos by comparing edge and gradient structure—not absolute brightness. Perfect for exposure‑adjusted, HDR, and color‑graded copies. Free, browser‑based, and 100% private.

Sakarto dHash duplicate finder interface showing gradient-based grouping of exposure-adjusted images

When you brighten a photo by 20%, every single pixel value changes. To an algorithm like aHash, which compares each pixel to the overall average brightness, that brightened version looks like a different image. The hash changes, and the duplicate is missed.

That’s where dHash (Difference Hash) comes in. Instead of recording absolute brightness, dHash records the direction of brightness change between adjacent pixels. When you brighten an image uniformly, the relative ordering of pixel brightness—which pixel is brighter than its neighbour—stays almost entirely the same. A brightened copy and the original produce nearly identical dHashes.

This makes dHash the algorithm of choice for photo collections with inconsistent exposure settings, HDR exports, color‑graded versions, or any scenario where the same image appears at different brightness levels.


What makes dHash different from aHash, BlockHash, and pHash?

All four algorithms produce a binary hash and compare using Hamming distance. But they encode fundamentally different visual properties:

AlgorithmEncodesSensitive toBest for
aHashAverage brightness per pixelOverall brightness levelSpeed, exact copies
BlockHashBlock‑averaged brightnessCompression artifacts, noiseNoisy, heavily compressed images
pHashLow‑frequency frequency contentFine edits, watermarkingPrecision, format conversions
dHashDirection of brightness changeExposure, brightness shiftsExposure‑adjusted, HDR, color‑graded copies

The key insight: dHash never compares absolute values. It only records the relative ordering. This makes it virtually immune to uniform brightness changes—and highly robust to contrast adjustments, gamma corrections, and the global tone mapping used in HDR processing.


How the algorithm works: a deep dive

Let’s walk through exactly what happens when you scan a folder with dHash.

Step 1: Resize to 17×16 pixels

Each image is drawn onto a canvas that is one pixel wider than it is tall—specifically 17×16 pixels. The extra column is what makes the horizontal gradient comparison possible: every pixel in the 16 columns has one neighbour to its right.

Fast Mode (enabled by default for JPEGs): Instead of decoding the full image, Sakarto reads the embedded EXIF thumbnail (typically 160×120 pixels). This makes JPEG scans 5–10× faster with negligible accuracy loss—the 17×16 grid is so small that the thumbnail is more than enough data.

Step 2: Convert to grayscale

Each of the 17×16 = 272 pixels is converted to a single brightness value using the standard luminance formula: Gray = 0.299 × Red + 0.587 × Green + 0.114 × Blue

Color information is discarded at this point. dHash doesn’t care about color—only about brightness transitions.

Step 3: Compare each pixel to its right neighbour

For each row (16 rows), and for each column (16 comparisons per row, stopping before the last column), the grayscale value of a pixel is compared to the grayscale value of the pixel directly to its right. If the left pixel is brighter than its right neighbour, the bit is 1. If it is darker or equal, the bit is 0. if (pixel(x, y) > pixel(x + 1, y)) bit = 1 else bit = 0

This produces 16 × 16 = 256 comparisons—one for each bit in the final hash.

Step 4: Produce the 256‑bit gradient hash

Reading across all 16 rows, each with 16 comparisons, produces a 256‑bit binary fingerprint. This hash encodes the direction of brightness change at 256 positions across the image—a compact map of the image’s edge and gradient structure.

Why this works for brightness shifts: When you uniformly increase brightness, every pixel gets brighter by roughly the same amount. The left pixel and the right pixel both shift up proportionally. The left pixel might go from 80 to 120, and its right neighbour might go from 60 to 100. Before the shift: 80 > 60 → bit is 1. After: 120 > 100 → bit is still 1. The relative ordering is preserved.

Step 5: Compare using Hamming distance

To compare two files, their 256‑bit hashes are XOR’d bit by bit. The number of positions where the bits differ is the Hamming distance. A distance of 0 means identical gradient patterns. The threshold slider controls the maximum Hamming distance allowed for two files to be grouped as duplicates. Lower = stricter.

Step 6: Aspect‑ratio pre‑check

Before comparing hashes, Sakarto checks whether the two files have similar aspect ratios. If one is 4:3 and the other is 16:9—differing by more than 10%—they’re skipped entirely. This prevents a tall portrait from matching a wide landscape even if their gradient patterns coincidentally align.

Step 7: Video processing

For videos, 3 frames are extracted at 1.5‑second intervals. Each frame produces its own 256‑bit dHash. The three hashes are combined by majority vote per bit to produce a single representative hash for the whole file. Video scanning pauses if you switch tabs (browser limitation) and resumes when you return.


What dHash finds well

Type of duplicateHow well it worksWhy
Exact byte‑for‑byte copies✅ ExcellentThe hash will be identical.
Same photo at different resolutions✅ ExcellentResizing to 17×16 removes resolution differences.
Brightness‑adjusted or exposure‑corrected copiesExcellentThe relative ordering of pixel brightness is preserved under uniform brightness changes.
HDR vs standard versions of the same scene✅ Very GoodGlobal tone mapping preserves most gradient directions.
Contrast‑tweaked versions✅ GoodContrast changes alter the magnitude of gradients but usually preserve direction.
Lightly color‑graded copies✅ GoodAs long as the grading doesn’t shift where edges appear.
Re‑compressed JPEG versions✅ GoodCompression artifacts may affect some bits but dHash remains stable.
Screenshots of the same image✅ Very GoodScreenshots preserve gradient structure.
Videos with similar structural content✅ GoodMultiple frames averaged together.
Heavily cropped copies⚠️ May missCropping shifts the position of edges in the grid.
Rotated or mirrored images❌ Won’t findRotation transposes horizontal gradients to vertical, mirroring reverses direction. Use ORB.
Images with heavy filtering that eliminates gradients⚠️ May missStrong posterization or blur can flatten gradients.
Very different scenes with similar composition⚠️ May over‑matchdHash encodes composition, not content—two shots with similar lines can match.

Understanding the Hamming threshold slider

The threshold slider is the most important control in dHash. It determines how many bit differences are allowed between two hashes before they stop being considered duplicates.

Threshold rangeWhat it doesWhen to use
0–5 (Very strict)Only near‑identical gradient patterns match. Very few false positives.Finding exact copies and very close re‑exports.
6–15 (Balanced)Catches resized, re‑compressed, brightness‑adjusted, and lightly edited copies.Default and recommended. dHash at 10–15 often catches brightness variants that other algorithms miss.
16–25 (Loose)Includes more approximate gradient matches. More false positives.If you’re missing duplicates that have significant composition changes or heavy edits.
30+ (Very loose)Groups images with broadly similar gradient structure.Only use for exploration. Expect many false positives—two different portraits with similar lighting can match.

Tip: Because dHash is insensitive to brightness, you may find that it catches exposure‑corrected copies at a lower threshold than you’d use with aHash. Start at 8–10 and raise only if needed.


How to use dHash: step by step

Step 1: Open the tool and select a folder

Go to the dHash duplicate finder page. Click 📁 Select Folder to Scan to open a native folder picker (Chrome/Edge). Or drag and drop a folder onto the page.

Tip: Make sure Fast Mode is checked. For JPEGs, this reads the embedded thumbnail instead of the full image—5–10× faster with near‑identical accuracy.

Step 2: Wait for the scan to run

A progress bar shows how many files have been processed. dHash is one of the fastest algorithms in Sakarto—each image requires only 272 grayscale conversions and 256 comparisons. Duplicate groups appear live as they’re found—you don’t need to wait for the full scan to finish before reviewing results.

Step 3: Adjust the threshold

After the scan completes, use the Hamming Threshold slider (0–50) to tune matching strictness. Release the slider to re‑cluster all results instantly using the new value—no re‑scanning needed. A background Web Worker handles the re‑comparison.

Step 4: Review the duplicate groups

Results are shown in numbered groups. Each group contains files with similar gradient structures.

  • Click a card to select it (blue border)
  • Ctrl+Click (Cmd on Mac) to add to the compare list (purple border)
  • Click the 🔍 icon on hover to preview full size
  • Right‑click any card for the context menu
  • Click & drag on empty space to box‑select multiple cards

Step 5: Use the Compare modal

Ctrl+Click two or more cards, then click ⚖️ Compare in the toolbar. A modal shows each file with:

  • Full metadata (dimensions, file size, format)
  • A similarity percentage
  • Copy, Move, and Delete buttons for each file
  • A pairwise similarity matrix for 3+ files

Important: dHash can occasionally group different scenes with similar compositional lines—two portraits with similar lighting, two corridor shots, etc. Always use Compare to verify before acting.

Step 6: Take action—Move, Delete, or Copy

Select files and use the toolbar buttons. With Queue Mode on (recommended), files are staged for review first:

  • 📋 Copy — copy filename(s) to clipboard
  • 📂 Move — stage for move to a named folder
  • 🗑️ Delete — stage for permanent deletion
  • ⚖️ Compare — view selected files side‑by‑side

Warning: Deletions are permanent. The File System Access API bypasses the recycle bin. Always use Queue Mode to review before executing.

Step 7: Execute queued actions

Switch to the Move Queue or Delete Queue tab in the sidebar to review staged files, remove any you changed your mind about, then execute when ready.


When to use dHash vs. the other 6 algorithms

Sakarto gives you seven visual algorithms for a reason—each one handles a different type of duplication problem. Here’s when to pick dHash over the others:

Color Signature — colour accuracy

Color Signature is the only algorithm that compares actual colour. Use it when colour accuracy matters.

Use dHash instead: Your copies have been brightness‑adjusted, exposure‑corrected, or color‑graded in ways that shift colour. Color Signature would see the colour differences as mismatches; dHash ignores colour and focuses on gradient structure, which remains stable.

aHash (Average Hash) — speed above all else

aHash is the fastest algorithm—it reads individual pixels and compares them to the overall mean.

Use dHash instead: Your images have been brightened, darkened, or exposure‑corrected. aHash’s mean‑based comparison is sensitive to overall brightness levels; dHash’s gradient‑based comparison is not.

BlockHash — noise tolerance

BlockHash averages brightness over blocks, making it tolerant of compression noise.

Use dHash instead: Your images are clean but have exposure variations. BlockHash is more tolerant of noise but less sensitive to the fine gradient structure that dHash captures.

pHash (Perceptual Hash) — the all‑rounder for format conversions

pHash uses the Discrete Cosine Transform to extract low‑frequency structural data. It’s more discriminating than dHash but slower.

Use dHash instead: You need speed and your copies are brightness‑adjusted. pHash is more sensitive to global brightness changes than dHash—it encodes frequency coefficients that shift with brightness.

wHash (Wavelet Hash) — speed and quality balance

wHash uses the Haar Wavelet Transform—similar quality to pHash at lower CPU cost.

Use dHash instead: You specifically want to ignore brightness shifts. wHash still encodes absolute brightness values through its wavelet coefficients; dHash deliberately discards them.

ORB (Feature Matching) — rotation, cropping, and perspective

ORB is the only algorithm that handles rotation, cropping, and perspective warping.

Use dHash instead: Your copies are not rotated or heavily cropped. dHash is 100× faster than ORB for large folders and handles brightness shifts better.


Algorithm quick reference

AlgorithmBest forColour‑aware?Handles rotation?Handles brightness shifts?Speed
Color SignatureSame colour palette, social media re‑uploads✅ Yes❌ No⚠️ ModerateFast
aHashLarge folders, speed priority❌ No❌ No⚠️ ModerateFastest
BlockHashHeavily compressed JPEGs, noisy images❌ No❌ No⚠️ ModerateVery Fast
dHashBrightness/exposure‑adjusted copies❌ No❌ NoExcellentVery Fast
pHashFormat conversions, all‑round reliability❌ No❌ No⚠️ ModerateFast
wHashSpeed + quality balance❌ No❌ No⚠️ ModerateFast
ORBRotated, cropped, perspective‑warped❌ No✅ Yes✅ GoodSlower

Privacy: your files never leave your device

Like every Sakarto tool, the dHash duplicate finder runs entirely in your browser:

  • Zero network activity after page load. Open DevTools → Network tab and verify: no outbound requests during any scan or file operation.
  • No accounts, no cookies, no analytics. The only localStorage data is your OS detection and checkbox preferences. No file names or scan results are ever saved.
  • Folder access is scoped and session‑only. Permission expires when you close the tab.
  • Purely static—no backend. Sakarto is HTML, CSS, and JavaScript. There is no server, no database, and no API receiving your data.

Frequently asked questions (dHash specific)

“How is dHash different from aHash, BlockHash, and pHash?”

All four produce a binary hash compared with Hamming distance, but they encode different image properties. aHash compares each pixel in a 16×16 grid to the overall mean brightness—it captures coarse light/dark layout. BlockHash averages 16×16 blocks and compares each to the median—more tolerant of compression noise but even coarser. pHash applies a Discrete Cosine Transform and encodes the dominant low‑frequency content—the most precise of the four. dHash is unique: it compares each pixel to its right‑hand neighbour, encoding the direction of brightness change rather than absolute brightness. This makes dHash insensitive to overall brightness level—the same image processed at a different exposure or brightness setting will produce the same dHash, because the relative ordering between adjacent pixels doesn’t change when you uniformly raise or lower brightness.

”Why exactly is dHash good at finding brightness‑adjusted copies?”

When you increase the overall brightness of an image, every pixel gets lighter by roughly the same amount. Pixel A might go from value 80 to 120, and its right neighbour B might go from 60 to 100. Before the adjustment: A (80) > B (60) — the bit is 1. After: A (120) > B (100) — the bit is still 1. The relative ordering is preserved. dHash records this ordering for all 256 adjacent pixel pairs, so uniform brightness and contrast adjustments leave the hash almost completely unchanged. The edge case is extreme adjustment that flattens gradients to near‑zero—if adjacent pixels become nearly identical (all white or all black), the relative ordering becomes noise‑driven and the hash degrades.

”Two clearly different photos are being grouped together. How do I fix it?”

dHash encodes edge and gradient structure, not image content. Photos with similar compositional lines—two corridor shots, two aerial field photos, two portraits with similar lighting direction—can have similar gradient patterns without being the same image. Fix: Lower the threshold slider to 5–8 to require much closer gradient matches. If false positives persist, try pHash (frequency‑domain content, more discriminating) or Color Signature (also compares colour). Always use the Compare modal to verify before acting on any group.

”I know two files are duplicates but they aren’t being grouped. What should I try?”

First, raise the threshold toward 15–20. Second, check aspect ratios—pairs differing by more than 10% are excluded by the pre‑check. Third, consider the type of edit: dHash handles brightness and contrast changes well, but significant colour grading that shifts where gradients appear, heavy cropping, or rotation will break the match. For rotated copies, use ORB. For colour‑graded copies where the subject and composition are the same but hues have shifted, try dHash at a higher threshold or pHash as an alternative.

”What does Fast Mode do, and is it safe to leave on?”

Fast Mode reads the small EXIF thumbnail embedded in JPEG files (usually 160×120 pixels) instead of decoding the full image. This is 5–10× faster with negligible accuracy loss for dHash, because dHash’s 17×16 pixel basis is tiny relative to most EXIF thumbnails. Leave Fast Mode on unless you notice unexpected groupings on JPEG files that go away when Fast Mode is off—which would suggest those files lack EXIF thumbnails and Fast Mode is falling back to partial data.

”Can dHash find HDR vs standard versions of the same photo?”

Usually yes, depending on how the HDR processing was applied. HDR processing typically boosts local contrast—bringing up shadow areas and pulling down highlight areas. This changes the absolute brightness of pixels but often preserves the direction of brightness gradients between adjacent pixels. If the HDR version simply applies global tone mapping (brightening overall), dHash will match it confidently. If it applies heavy local tone mapping that reverses local gradients in shadow or highlight regions, some bits will flip and matching will depend on how many gradients were reversed relative to the threshold.

”Why does video scanning pause when I switch tabs?”

Browsers throttle background video element processing when a tab is hidden, stopping frame extraction. Sakarto detects this via the Page Visibility API and pauses video scanning automatically, resuming the moment you return. Image hashing runs entirely in a background Web Worker, which is not subject to tab‑visibility throttling—images keep scanning at full speed no matter which tab you’re viewing.

”Can I recover files after deleting them?”

No. The File System Access API’s remove() method bypasses the OS Recycle Bin entirely and permanently deletes files. Queue Mode is on by default to prevent accidents: files are staged for review before execution. Before deleting, use the full‑size preview icon and the Compare modal to verify the files in each group. If in doubt, Move to a “Sakarto‑Duplicates” subfolder first—you can always delete from there later once you’re certain.

”What file types are supported?”

Images: JPEG, PNG, GIF, WebP, BMP. Videos: MP4, WebM, MOV, MKV. Files over 40 MB are skipped. HEIC/HEIF, SVG, RAW formats, and TIFF are not supported due to browser decoder limitations. Convert RAW or HEIC files to JPEG or PNG in your photo editor before scanning.

”Does this work on Firefox or Safari?”

Scanning, hash computation, result display, and the Compare modal all work in Firefox and Safari. Move and Delete require the File System Access API (Chrome 86+ and Edge 86+ only). In other browsers, scan and review results normally, then use Download List to export a report and handle files manually.


Final thoughts

dHash is the algorithm you reach for when your photo library contains the same image at different brightness levels—exposure‑corrected variants, HDR exports, color‑graded versions, or images from different cameras with different default brightness settings.

It’s particularly effective for:

  • Exposure‑adjusted copies. The same photo brightened or darkened by a few stops.
  • HDR vs standard versions. HDR processing often preserves gradient directions.
  • Color‑graded variants. As long as the grading doesn’t shift where edges appear.
  • Mixed‑camera libraries. Different cameras have different default brightness—dHash normalises this away.

Where dHash falls short—rotated, heavily cropped, or colour‑shifted copies—other Sakarto algorithms fill the gap. Use ORB for geometric transforms, pHash for precision edits, or Color Signature for colour‑aware matching.

But for brightness‑adjusted photo collections, dHash is the algorithm that finds the duplicates the others miss.

Ready to find duplicate images and videos with exposure variations?

May 29, 2026
⏱ 18 min read
🇬🇧 English