Second Brain documentation

ADR 0062 – Scan de document multipage

Accepté (2026-10-16, mode autonome)

← Toutes les décisions

ADR 0062 – Scan de document multipage

Statut : Accepté (2026-10-16, mode autonome)

Item 30 du jalon 3 (vague 2 du document d’idées) : photographier les pages d’un courrier, d’un bail ou d’une facture, et obtenir un seul PDF rangé dans l’inbox, comme le ferait une application de scan.

Contexte

  • « Prendre une photo » (ADR 0034) envoie une image par nœud. Un document de trois pages devient trois nœuds.
  • Un nœud peut porter plusieurs fichiers (ADR 0032), mais trois photos ne font pas un document : on ne peut ni l’envoyer, ni l’imprimer, ni l’archiver d’un bloc.
  • Aucune bibliothèque PDF n’est dans le projet. L’environnement de développement n’en télécharge pas de nouvelle (pas d’accès aux dépôts publics).
  • Les photos d’un téléphone sont des JPEG de 3 à 5 Mo, parfois tournées par leur seule étiquette EXIF, parfois en HEIC.

Décision

  • Dans le navigateur : chaque page est préparée avant l’envoi (ScanImages), une à une pour ménager la mémoire d’un téléphone.
    • Elle est décodée avec son orientation EXIF (createImageBitmap, imageOrientation: from-image), donc redressée.
    • Elle est réduite à 2000 px au plus grand côté (lisible à l’impression A4) et réencodée en JPEG à 85 % sur fond blanc (une image transparente ne devient pas noire).
    • Une image que le navigateur ne sait pas décoder (HEIC hors Safari) est refusée avec son numéro de page, avant tout envoi.
  • Dialogue « Scanner un document », depuis le menu « + Capturer » et chargé à la demande :
    • un titre, proposé « Document scanné du 16/10/26 » ;
    • « Ajouter une page » ouvre l’appareil photo (dos) sur un téléphone, le choix d’images (plusieurs à la fois) sur un ordinateur ;
    • des vignettes numérotées avec Monter, Descendre et Retirer ; le focus suit la page déplacée ;
    • « Créer le PDF (n pages) ». 50 pages au plus, 55 Mo au plus une fois préparées (sous la limite d’une requête, 60 Mo) : au-delà, « Document trop lourd ».
    • Le dialogue ne se ferme pas sur une navigation (Annuler est là pour ça) ; fermé pendant la préparation, il n’envoie rien. Pendant l’envoi, l’ajout de pages est coupé.
    • Le focus suit une page déplacée, va à la page suivante après un retrait, et reste sur « Créer » pendant l’envoi.
  • Serveur : POST /api/scans (multipart pages, title, parentId, inbox vrai par défaut).
    • Chaque page doit être un JPEG que /DCTDecode lit partout : marqueur de début, puis un segment SOF0 à SOF2 (baseline, séquentiel étendu, progressif), 8 bits, gris ou couleur. Le CMJN (sens des valeurs incertain sans segment Adobe), le sans perte, le hiérarchique et le codage arithmétique sont refusés : un navigateur ne les produit pas. Sinon, refus 400 sur pages[i], avec un message qui nomme la page. 15 Mo au plus par page.
    • Le PDF est écrit par ScanPdf, sans bibliothèque : PDF 1.4, une page A4 par image (portrait ou paysage selon l’image), l’image centrée avec 7 mm de marge, insérée telle quelle (/DCTDecode, aucun décodage côté serveur), le titre dans les informations du document, une table des références exacte.
    • Le PDF est écrit au fil de l’eau dans un fichier temporaire, supprimé ensuite : en mémoire, il doublerait les pages déjà lues.
    • Le nœud est créé comme un fichier déposé (NodeFileService) : titre, PDF rattaché sous « titre.pdf », dans l’inbox, dans une transaction (node.created puis file.attached). Une barre du titre (« 16/10/26 ») devient un tiret dans le nom du fichier : l’assainissement des noms la lirait comme un dossier.
  • Après : la notification « « Titre » ajouté à l’inbox (3 pages) » propose « Ouvrir » ; le compteur de l’inbox est relu. La fiche montre le PDF dans l’aperçu des fichiers.

Alternatives écartées

  • PDF dans le navigateur (jsPDF, pdf-lib) : une dépendance de plus de 100 Ko, à télécharger (impossible ici) et à charger sur le téléphone. Le serveur assemble en quelques millisecondes.
  • Bibliothèque côté serveur (PDFBox) : même obstacle de téléchargement, et elle décoderait les images pour rien. Le format écrit ici est petit et testé (structure et table des références).
  • Plusieurs fichiers image sur un nœud (ADR 0032) : possible dès aujourd’hui, mais ce n’est pas un document qu’on envoie ou qu’on imprime.
  • Redressement de perspective, détection des bords, OCR : utiles, mais hors de portée sans bibliothèque de vision. La recherche dans les PDF (OCR) est une autre ligne du cahier.

Conséquences

  • La qualité dépend de la photo : pas de recadrage automatique, pas de correction de perspective ni de contraste.
  • Le PDF contient des images, pas de texte : il n’est pas encore trouvé par la recherche plein texte.
  • Les pages sont lourdes en mémoire pendant la préparation sur un vieux téléphone : elles sont traitées une à une, les vignettes sont décodées à la demande et le canvas est libéré après chaque page.
  • Sur Chrome Android, capture ouvre directement l’appareil photo : les photos déjà prises dans la galerie se choisissent depuis un ordinateur.
  • Le titre part en paramètre de requête (client généré) : il peut figurer dans les journaux d’accès du proxy.