Skip to content

✨ feat(Metadata): exposer les EXIF du RAW #33

Description

@ronan-develop

À ne pas démarrer avant #32 (orientation), ni avant un retour d'usage réel. Les raisons sont en bas.

Le constat

TiffReader lit déjà ces données à chaque extraction — il les traverse pour trouver la preview, et les jette. Vérifié sur de vrais fichiers :

── Nikon D750 (NEF) ──
  Make / Model     NIKON CORPORATION / NIKON D750
  DateTime         2017:01:15 21:38:27
  Orientation      1
  ISO              100
  FocalLength      350        ← RATIONAL : c'est 35 mm, pas 350
  GPSIFD           158868     ← pointeur, pas une valeur
  (+ 27 autres tags EXIF)

── Sony α7 (ARW) ──
  LensModel        FE 28-70mm F3.5-5.6 OSS

exif_read_data() de PHP ne lit pas les RAW — ni CR3, ni la plupart des NEF. Ce package serait le seul en PHP à extraire les EXIF d'un CR3, parce qu'il a déjà IsoBmffBoxReader pour trouver CMT1/CMT2, qui contiennent des IFD TIFF que TiffReader sait lire.

Pourquoi c'est utile

Ceux qui manipulent des RAW sont des photographes : ils retravaillent leurs images ensuite. Le boîtier, l'objectif, la focale, l'ouverture, la date, le lieu — ce n'est pas une donnée technique, c'est le contexte de la photo. C'est ce qui distingue une galerie d'un dossier d'images.

La forme : un value object, pas un fichier

Pas de writeDescriptorFile(). Écrire, c'est décider où, sous quel nom, dans quel format — imposer une politique de stockage à tous les consommateurs, et casser la promesse que la librairie n'écrit jamais sur disque. C'est le même raisonnement que pour $preview->jpegData : on rend les octets, l'appelant décide.

Symétrique à ExtractedPreview :

$metadata = $extractor->readMetadata($path);

$metadata->make;           // 'NIKON CORPORATION'
$metadata->model;          // 'NIKON D750'
$metadata->lens;           // 'FE 28-70mm F3.5-5.6 OSS'
$metadata->takenAt;        // DateTimeImmutable
$metadata->exposureTime;   // '1/250'
$metadata->fNumber;        // 1.8
$metadata->iso;            // 100
$metadata->focalLength;    // 35
$metadata->gps;            // ?Coordinates

L'appelant écrit son fichier descriptif s'il en veut un — un JsonSerializable suffit :

file_put_contents('photo.json', json_encode($metadata));

Les vrais chantiers

1. Les RATIONAL. IfdEntry ne garde aujourd'hui que le numérateur — d'où « focale 350 ». Or tous les champs intéressants sont des RATIONAL : vitesse (1/250), ouverture (f/1.8), focale. Il faut porter le couple numérateur/dénominateur jusqu'au value object. C'est le gros du travail, et c'est indépendant de l'orientation.

2. Le GPS. GPSIFD est un pointeur, pas une valeur. Il faut suivre l'IFD, lire lat/lon en RATIONAL sexagésimal (degrés, minutes, secondes), appliquer les références N/S/E/W. Faisable — tout est là — mais c'est un morceau à part entière.

3. Le CR3. Pas de TIFF direct : les EXIF vivent dans CMT1/CMT2. TiffReader::fromRange() — écrit pour #32 — est exactement la pièce qui manquait.

4. Le périmètre. 33 tags sur le D750. Lesquels exposer ? Un value object à 30 propriétés est illisible ; six bien choisies servent 95 % des cas. C'est ce que seul l'usage réel peut dire.

⚠️ Vie privée

Le GPS et le numéro de série sont précisément ce dont on se méfie pour les fixtures de ce repo. Une galerie qui affiche les EXIF d'une photo partagée peut exposer le domicile du photographe.

La librairie doit les rendre — c'est son rôle, elle lit ce qui est là. Mais l'application décidera quoi montrer sur un partage public. À documenter explicitement.

Version

Une mineure : readMetadata() est une méthode nouvelle, extract() ne bouge pas. 1.2.0 si #32 sort en 1.1.0.

Pourquoi attendre

  1. 🔧 fix(ExtractedPreview): exposer l'orientation EXIF — les previews portrait sortent couchées #32 d'abord : TiffReader::fromRange() est écrit pour lui, et les EXIF en dépendent. Mener les deux en parallèle, c'est concevoir la même pièce deux fois.
  2. L'orientation est un EXIF (tag 0x0112). La faire d'abord répond aux questions qui conditionnent toute l'API : où lire un tag quand la preview est dans un sous-IFD, comment brancher CMT1.
  3. Un usage réel ensuite : il dira si un photographe veut les 33 tags ou seulement six. Concevoir une API sur une intuition, c'est ce qui produit une 2.0.0 six mois plus tard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions