Skip to content

v1.4.1 — large photo libraries were losing similar pictures

Choose a tag to compare

@RobertasTa RobertasTa released this 26 Aug 07:52
· 17 commits to master since this release

What's fixed

Large photo collections were quietly losing similar pictures.

Visually similar photos are found through a fingerprint: each picture is
reduced to 64 bits, and pictures whose fingerprints nearly match are grouped
together. To compare them quickly the fingerprints are sorted into groups by
a shared slice, and only pictures inside the same group are compared with
each other.

That grouping had a ceiling of 300. Anything above it was skipped — and
skipped without a word. The result was worse than a slow scan: a larger
photo library could return fewer similar pictures than a smaller one.
Reduced to its clearest form:

Pictures scanned Similar groups found
200 1 group, 200 pictures
320 none at all

Adding pictures did not add results; it made them disappear.

How it was found. Not in tests — by measuring three real archives with
about 180,000 photographs in them:

Archive Pictures Distinct fingerprints Largest group
Home NAS share 54,200 13,341 217
NAS (five shares) 66,537 19,621 334 — over the ceiling
External drive 60,066 28,226 284

The ceiling was not a distant edge case. It was already being crossed on an
ordinary home collection, and the pictures it dropped were never mentioned
to anyone.

One assumption died along the way, and it is worth passing on: collection
size is not what fills a group. The archive with the most fingerprints
had a smaller group than the middle one. What fills a group is how many
near-identical pictures a collection holds — dark frames, scanned documents,
screenshots. A small, uniform archive can cross the ceiling sooner than a
large, varied one.

What changed. The ceiling is a workload limit, not part of the algorithm:
how many pictures count as similar does not depend on it. It now sits at
10,000, which is about 15 seconds of work in the worst case — measured, not
guessed, at 3.3 million comparisons per second. And if it is ever reached,
the scan says so in plain words, in all four languages, instead of leaving
pictures uncompared in silence:

1234 pictures were left uncompared — too many look-alikes in one place
(narrow the folders)

Two new tests cover both halves: that nothing disappears below the ceiling,
and that reaching it is always reported. Both were checked with the fix
switched off first — a test that does not fail without the fix is theatre.

Honesty notes

  • This was our own defect, not a rare edge case, and it had been shipping
    since visual comparison existed. If you scanned a large photo library with
    an earlier version and it reported few or no similar pictures, that answer
    may have been wrong. It is worth scanning again.
  • The fix raises a limit and adds a warning. It does not change which
    pictures are considered similar — the matching rule is untouched.
  • A second, related weakness is known and not fixed yet: pictures far
    above 89 million pixels can be skipped silently by the imaging library.
    It has not yet been confirmed on real files, and it will be treated the
    same way — measured first, then reported to you rather than hidden.

Checksums

MD5:    392c1e4c22beaed322742f1fcad7b1e6
SHA256: 6F2D34B7A7CA562EF817516E21BC03F7BC73805F44785F629C8A542CFB193E95

VirusTotal: an unsigned PyInstaller executable always collects a few
generic machine-learning flags — v1.3 was flagged by 4 engines out of 67,
all of them heuristics, while Avast, Avira, BitDefender, ClamAV, Kaspersky,
ESET and Microsoft Defender reported it clean. Czkawka, a 32,000-star Rust
project, documents the same thing about its own binaries. You do not have to
take our word for it: paste the SHA256 above into
virustotal.com and look for yourself.

🤖 Built together with Claude (Anthropic AI).