Migration des dimensions des images avec prise en charge de l'EXIF d'orientation

Bonjour à toutes et tous,

Ouvert il y a plusieurs mois maintenant, le chantier de la gestion des EXIF d’orientation sur les images (notamment en mode portrait) est près d’aboutir (fix: traiter de manière uniformisée les images en mode portrait ou miroir selon leur EXIF d'orientation (!6078) · Requêtes de fusion · spip / spip · GitLab + feat: gestion de la migration des dimensions enregistrées en base, avec... (!5012) · Requêtes de fusion · spip / medias · GitLab + refactor: s'appuyer sur les évolutions de spip/spip pour le filtre `image_oriente_selon_exif` (!4734) · Requêtes de fusion · spip / images · GitLab + fix: réinitialiser l'orientation des images en mode portrait... (!4902) · Requêtes de fusion · spip / bigup · GitLab).

Mais il demeure un problème, et pas des moindres lorsque des personnes ont activé le redimensionnement des images au téléchargement via BigUp : le redimensionnement actuellement (avant fix: réinitialiser l'orientation des images en mode portrait... (!4902) · Requêtes de fusion · spip / bigup · GitLab) ne prend pas en compte l’EXIF d’orientation et donc on se retrouve avec des images « désorientées » (un portrait est transformé en paysage par exemple) avec une incohérence entre la vignette générée (correctement orientée) et l’image telle qu’elle est réellement.

Ainsi, sans le fix proposé sur BigUp :

php > dump(exif_read_data('IMG/jpg/landscape_8-4.jpg'));
^ array:14 [
  "FileName" => "landscape_8-4.jpg"
  "FileDateTime" => 1731248746
  "FileSize" => 16873
  "FileType" => 2
  "MimeType" => "image/jpeg"
  "SectionsFound" => "ANY_TAG, IFD0, EXIF"
  "COMPUTED" => array:5 [
    "html" => "width="200" height="150""
    "Height" => 150
    "Width" => 200
    "IsColor" => 1
    "ByteOrderMotorola" => 1
  ]
  "Orientation" => 8
  "XResolution" => "72/1"
  "YResolution" => "72/1"
  "ResolutionUnit" => 2
  "Exif_IFD_Pointer" => 90
  "ExifImageWidth" => 450
  "ExifImageLength" => 600
]

Avec le fix sur BigUp :

php > dump(exif_read_data('IMG/jpg/landscape_8-5.jpg'));
^ array:14 [
  "FileName" => "landscape_8-5.jpg"
  "FileDateTime" => 1731248844
  "FileSize" => 16917
  "FileType" => 2
  "MimeType" => "image/jpeg"
  "SectionsFound" => "ANY_TAG, IFD0, EXIF"
  "COMPUTED" => array:5 [
    "html" => "width="150" height="200""
    "Height" => 200
    "Width" => 150
    "IsColor" => 1
    "ByteOrderMotorola" => 1
  ]
  "Orientation" => 8
  "XResolution" => "72/1"
  "YResolution" => "72/1"
  "ResolutionUnit" => 2
  "Exif_IFD_Pointer" => 90
  "ExifImageWidth" => 450
  "ExifImageLength" => 600
]

Je pensais avoir trouvé là un moyen de repérer les images ainsi modifiée automatiquement mais en fait non : les ExifImageWidth et ExifImageLength ne sont pas toujours présentes, et l’on ne peut donc s’appuyer sur ces éléments pour « corriger » les transformations opérées par BigUp…

Du coup, on en revient à la première solution que j’avais imaginée, bien plus radicale et moins « plaisante » : la suppression pure et simple des EXIF d’orientation de ces images.

L’idée serait donc :

  • d’identifier la date d’application du patch fix: réinitialiser l'orientation des images en mode portrait... (!4902) · Requêtes de fusion · spip / bigup · GitLab en se basant sur le champ maj de la table spip_meta pour nom = 'bigup_base_version' AND valeur > 1.0.2 mettons (mais ça nécessite d’utiliser l’attribut schema pour autre chose que ce pour quoi il est prévu) ;
  • on peut alors sélectionner les jpg (les tiff n’étant pas redimensionnés par BigUp) avec un champ maj inférieur à la date d’application du patch de BigUp ;
  • pour ces images et seulement celles-ci, on supprime l’EXIF d’orientation.

Sur cette question de la suppression d’un EXIF, il me semble qu’il nous faudrait passer par une librairie tierce, en l’occurrence sans doute GitHub - FileEye/pel: PHP Exif Library - library for reading and writing Exif headers in JPEG and TIFF files using PHP.

Je me vois mal intégrer cela à Medias mais je me demande comment procéder : un plugin spécifique avec une commande SPIP Cli ? Une page permettant de déclencher l’action via l’interface ?

Au détour d’une release party on s’est finalement dit que pour le passé, tant pis… si des gens ont laoissé des images tordues… et bien… tant pis…

Indépendamment des errements du passé, ya aussi la question des futures rotations d’images avec le bouton spip de rotation à la main : quand par exemple une image à un EXIF portrait et que l’utilisateur demande à la tourner de 90°, que faut il faire ou ne pas faire / qu’est ce qui sera fait / avec l’orientation EXIF ?

Dans ce cas là, lorsque l’on fait une action de rotation via SPIP, l’image créée ne possède pas d’EXIF.

Oui, comme on le disait pendant la release de ce matin, « le mieux est l’ennemi du bien ». Le travail que @bricebou a fait sur le sujet est déjà un sacré chantier, rien ne sert de charger la barque, et on aura tout le loisir d’y revenir par la suite si on pense que c’est vraiment problématique pout le cas de bigup.

Complètement d’accord ! Régler le bug d’orientation c’est déjà énorme. Si des sites ont besoin de mettre à jour d’anciennes images ce serait sympa de fournir une solution. Mais indépendamment de SPIP et de médias.

Alors, les échanges de ce matin ont mis en avant des situations que je n’avais pas imaginées (sites existant même avant l’apparition de BigUp, images non transformées parce que passant sous le seuil configuré dans BigUp, configuration BigUp variant au gré des époques de vie d’un site…)
Bref, tout cela pour dire in fine que, du moins pour le moment, on ne voit pas de moyen d’identifier de manière robuste les images ayant été transformées par BigUp.
Je ferme donc le sujet ici.

2 « J'aime »