Aller au contenu
Aubui · Scanner
Composants

ScannerNouveau

La caméra lit un papier en direct : contour du papier, conseils (« trop sombre », « flou, ne bouge plus », « reflet : incline un peu », « rapproche-toi »), photo prise toute seule quand c’est stable et net, recadrée et redressée. Avec un serveur qui lit, ce qu’il trouve est entouré sur le papier en direct (rouge, puis vert une fois vérifié) et le morceau lu s’envole vers AIA. Tout le traitement de l’image se fait dans le téléphone, en JavaScript maison, sans bibliothèque. Premier usage : Gestion › Ajouter un papier.

Essayer

C’est le composant réel. Ici, aucun serveur : les réponses de lecture sont simulées dans la page (rien ne part sur le réseau) et la carte fictive est dessinée dans la page. Avec ta caméra, montre n’importe quel papier posé sur une table : les cadres simulés se placent dans la bande du bas.

Installer

Rien à charger à la main : aubui.js crée window.AubuiScanner tout de suite et récupère aubui-scanner.js (≈ 39 Ko non compressé, ≈ 13 Ko en gzip, gardé un an en cache) seulement au premier ouvrir() ou precharger(), ou si la page contient un [data-aubui-scanner]. Le style est dans aubui.full.css ; une page qui garde une vieille feuille en cache reçoit components/scanner.css du composant lui-même.

API window.AubuiScanner

JS
var s = AubuiScanner.ouvrir({
  envoi: '/api/scanner',          // le serveur qui lit (POST du JPEG brut) — ou une fonction (blob, infos) → Promise<réponse>
  jeton: JETON, entete: 'X-Gestion-Token',   // l’en-tête CSRF de la page
  type: 'cni',                    // le type déjà connu (en-tête X-Scanner-Type), sinon le serveur le devine
  faces: 'auto',                  // 1, 2 (recto + verso) ou auto : verso demandé si le serveur dit recto_verso
  titre: 'Scanner un papier',
  declencheur: bouton,             // où rendre le focus à la fermeture
  surLecture: function (reponse, face) {},
  surPhoto: function (fichiers, infos) {   // fichiers : [File recto, File verso?] (JPEG redressés)
    // infos : { type, champs: {cle: {label, valeur, affiche, sur}}, faces: [{face, largeur, hauteur, manuel}] }
  },
  surFermeture: function (raison) {}       // echap · bouton · photo · api
});
s.prendre();   // prendre la photo maintenant
s.fermer();
OptionRôle
envoiSans lui : contour, conseils et photo seulement. Avec une URL : toutes les intervalle ms (1500 par défaut), la zone du papier redressée, en gris, ≤ 60 Ko (JPEG), part en POST (corps brut image/jpeg, credentials: same-origin). Avec une fonction : elle reçoit le Blob et rend la réponse (démo, bancs).
imagePartir d’une photo (File, Blob, URL, <img>, <canvas>) au lieu de la caméra : même contour, même lecture, même redressement.
facesAprès le recto, « Retourne le papier : montre le verso » (bouton « Pas de verso »).
Réponse du serveur{type: {id, label, recto_verso}, champs: [{cle, label, affiche, sur, boite: [[x, y] × 4]}], guide, complet} — boîtes en coordonnées 0-1 de l’image envoyée (= le papier redressé) : le composant les reporte sur l’image en direct, même si le papier bouge. sur : vérifié (chiffres de contrôle) → vert. guide : ce qu’AIA demande (« approche la bande du bas »). complet : la photo peut être prise tout de suite.
Évènementaubui:scanner sur document, detail.etape : ouvert · camera (ok) · lecture (reponse) · trouve (champs) · photo · fini · ferme.

Comment ça marche

  • Contour (≈ 10 fois par seconde, sur une copie de 220 px) : seuil d’Otsu, la plus grande tache claire ou sombre qui ne touche pas trois bords, son enveloppe convexe, puis le quadrilatère de plus grande aire. Le même calcul tourne côté serveur (Redresseur.php) pour remettre droites les photos déjà rangées.
  • Conseils : lumière moyenne du papier (trop sombre), part de pixels blancs brûlés (reflet), taille du papier dans l’image (rapproche-toi / recule), déplacement des coins (ne bouge plus), variance du laplacien sur un morceau à pleine résolution (flou).
  • Photo : stable et net depuis ~0,6 s (lecture complète) ou ~2,6 s (sinon) → image pleine résolution redressée par homographie (bilinéaire), au format carte (85,6 × 54) ou A4 quand c’est proche, JPEG 0,9, 2400 px au plus.
  • Animation : le morceau lu est découpé dans l’image du moment, glisse au centre, puis s’envole vers la pastille AIA qui pulse. « Réduire les animations » : il apparaît au centre en fondu, sans vol ni pulsation, et le tracé ne défile plus.
Accessibilité
  • role="dialog" + aria-modal ; le focus reste dans le scanner (Tab / Maj+Tab), Échap ferme et rend le focus. Un panneau Aubui ouvert dessous laisse faire.
  • Les conseils sont lus (aria-live="polite"), sans clignoter (un conseil reste au moins 0,5 s) ; ce qu’AIA a lu est aussi écrit en clair sous l’image (« ✓ Nom : … », « (vérifié) »).
  • Déclencheur toujours disponible (« Prendre la photo maintenant »), et « Choisir une photo » au clavier.
  • Sans caméra ou caméra refusée : un message clair et « Choisir une photo » prend la place du déclencheur. Dans l’app Android, la caméra est demandée par l’app (autorisation système) puis accordée à la page.
Aubui · design system AUBOTA · version 2026-10-30-7 · API figée · README · Une nouveauté Aubui = une section ici.