exif(): read HEIF/HEIC originals with exifreader (closes #145)
check / check (push) Successful in 1m21s

photo.exif() and backup-metadata --exif read EXIF with exifreader,
which reads JPEG, HEIC/HEIF, AVIF, PNG and WebP, so a HEIC original or
a live photo's HEIC image gets its EXIF. exifreader replaces
exif-reader and the hand-written JPEG segment scan. PhotoExif is
unchanged. The exif field of backup-metadata --exif is now
exifreader's tag output, and exifRaw holds the whole EXIF block it
could not read. Tests use a real 933-byte HEIC fixture, test/exif.heic,
whose recipe is in test/exif-heic.ts.

Model: opus-5-5
This commit is contained in:
2026-10-01 18:22:00 +00:00
parent 2b598d3622
commit a13ec66bca
12 changed files with 307 additions and 206 deletions
+13 -5
View File
@@ -224,7 +224,7 @@ quak/
backup.ts resilient full-account backup with dedup
metadata-backup.ts
backup-metadata: the metadata quak keeps, as JSON
exif.ts EXIF read from a JPEG's bytes
exif.ts EXIF read from an image's bytes with exifreader
mldata-fetch.ts fetch + decrypt per-file ML data
filename.ts safe file names from server metadata
errors.ts error types shared across layers
@@ -495,8 +495,15 @@ Ente's clients name them (`IMG_0001.heic` and `IMG_0001.mov`). With
`--out PATH`, the image is written to `PATH` and the video beside it, with
`PATH`'s name and the video's extension; a `PATH` with the video's extension is
refused. `backup-metadata --exif` (alias `--all`) additionally fetches each
file's original through the cache and records its XMP metadata and, for a JPEG,
its EXIF metadata and dimensions. `collections`, `files`, `backup`,
file's original through the cache and records, from it or a live photo's image,
its XMP metadata, its EXIF metadata and, for a JPEG, its dimensions. EXIF is
read with [exifreader](https://github.com/mattiasw/ExifReader) from any image
format it reads, JPEG, HEIC/HEIF, AVIF, PNG and WebP among them. The record's
`exif` field is exifreader's EXIF tag output: each tag by name, with its
`value`, `description` and `computed` value. Dumps written before 2026-10-01
hold `exif-reader`'s `Image`, `Photo` and `GPSInfo` groups there instead. An
EXIF block exifreader finds but reads no tag from is recorded, base64, as
`exifRaw`, with the reason in `exifError`. `collections`, `files`, `backup`,
`helper list-missing-thumbnails` and `helper fix-missing-thumbnails` take
`--json` for machine-readable output.
@@ -720,8 +727,9 @@ Four async methods may download:
each absent when the file lacks it. GPS values are signed decimal degrees and
metres. `dateTimeOriginal` is the camera's clock reading held in the `Date`'s
UTC fields; `offsetTimeOriginal`, when present, is that clock's offset from
UTC. Only a JPEG's EXIF is read: any other original gives `{}`, and a video
gives `{}` without being downloaded.
UTC. EXIF is read from any image format exifreader reads: JPEG, HEIC/HEIF,
AVIF, PNG and WebP, a live photo's image included. Any other original gives
`{}`, and a video gives `{}` without being downloaded.
They serve from the on-disk content cache when the bytes are present and
otherwise fetch through the pools; `original()`, `content()` and `exif()` also