L'art ASCII dans le navigateur et le terminal
L’idée est simple : prendre une image, mesurer la luminosité de chaque pixel et le remplacer par un caractère. Les caractères denses comme @ ou # représentent les zones sombres, tandis que les plus légers comme . ou représentent les zones claires. En alignant suffisamment de ces substitutions sur une grille, on obtient une image reconnaissable entièrement composée de texte.
Ce principe fondamental alimente à la fois l’art ASCII dans le terminal et l’art ASCII dans le navigateur, et les implémentations modernes l’ont poussé bien au-delà de l’ASCII 7 bits classique.
Points clés
- L’art ASCII associe la luminosité des pixels à des caractères issus d’une palette triée, où les glyphes denses comme
@représentent les zones sombres et les glyphes épars comme.représentent les zones claires - Les éléments de bloc Unicode et les motifs Braille offrent une résolution nettement supérieure aux palettes de caractères ASCII traditionnelles
- Les implémentations navigateur s’appuient sur les données de pixels du
<canvas>et le CSS monospace, tandis que les moteurs de rendu terminal utilisent les séquences d’échappement ANSI pour la couleur - Les capacités des terminaux varient considérablement — de l’ANSI 16 couleurs de base au true color 24 bits, SIXEL et le protocole graphique Kitty
Fonctionnement de la correspondance pixel-caractère
Chaque moteur de rendu ASCII suit approximativement le même pipeline :
- Échantillonner l’image source ou la trame vidéo dans une grille de cellules
- Calculer la luminosité moyenne (luminance) de chaque cellule
- Associer cette valeur de luminosité à un caractère d’une palette triée
- Afficher la grille de caractères résultante avec couleur optionnelle
Une implémentation JavaScript basique ressemble à ceci :
const palette = ' .:-=+*#%@';
function brightnessToChar(brightness) {
const index = Math.floor((brightness / 255) * (palette.length - 1));
return palette[index];
}
Ici, brightness est censé être une valeur entre 0 (noir) et 255 (blanc). La fonction la normalise en un index dans la chaîne de palette, où les premiers caractères représentent les tons clairs et les derniers représentent les tons sombres.
La qualité du résultat dépend fortement de votre palette de caractères. L’ASCII classique vous donne environ 10 à 15 niveaux de nuances utilisables. Les implémentations modernes font mieux.
Au-delà de l’ASCII : graphiques en mode texte avec Unicode
Les graphiques en mode texte avec Unicode déverrouillent une résolution nettement supérieure. Au lieu d’une palette ASCII éparse, vous pouvez utiliser :
- Les éléments de bloc (
█ ▓ ▒ ░) pour quatre niveaux de nuances par cellule - Les motifs Braille (
⣿ ⠿ ⠛) qui encodent jusqu’à 8 points dans un seul caractère, permettant une résolution effective plus élevée que les palettes ASCII traditionnelles - Les caractères de tracé de boîtes pour des mises en page structurées et des bordures
Chafa, une visionneuse d’images pour terminal, utilise les caractères de bloc Unicode et Braille pour rendre des images à une qualité quasi photographique dans un terminal. La différence par rapport à l’ASCII simple est frappante.
Discover how at OpenReplay.com.
L’art ASCII dans le navigateur : approches Canvas et WebGL
Le rendu ASCII JavaScript dans le navigateur utilise généralement un élément <canvas> comme source d’image. Le processus :
- Dessiner une image ou une trame vidéo sur un canvas hors écran
- Lire les données de pixels avec
ctx.getImageData() - Échantillonner la grille de pixels et associer chaque cellule à un caractère
- Rendre le résultat dans un élément
<pre>ou sur un canvas en utilisantfillText()
Des bibliothèques comme p5.js simplifient cette tâche, vous permettant de traiter des flux webcam en direct ou des trames vidéo en temps réel. Pour de meilleures performances, les shaders WebGL peuvent gérer l’échantillonnage de luminosité et la recherche de caractères sur le GPU, ce qui compte lorsque vous rendez une vidéo complète à 30 fps.
Pour un affichage statique, la configuration HTML/CSS est minimale mais importante :
.ascii-art {
font-family: monospace;
white-space: pre;
line-height: 1;
letter-spacing: 0;
}
Sans white-space: pre, le navigateur réduit les espaces et détruit la mise en page. Sans police monospace, les caractères ont des largeurs inégales et la grille s’effondre. Définir letter-spacing: 0 empêche les légers espaces horizontaux que certains navigateurs introduisent par défaut.
Graphiques ASCII dans le terminal : couleur ANSI et variabilité des protocoles
Dans les environnements de terminal, les caractères ASCII ou Unicode sont écrits sur la sortie standard. La couleur est ajoutée via des séquences d’échappement ANSI. Les terminaux modernes prennent en charge la sortie 24 bits (true color) :
printf '\033[38;2;255;100;0m%s\033[0m\n' "orange text"
Cela définit la couleur de premier plan sur RGB(255, 100, 0) en utilisant la séquence 38;2;R;G;B, puis réinitialise le formatage avec \033[0m.
Des outils comme jp2a et ascii-image-converter utilisent cette approche pour produire des graphiques ASCII colorés dans le terminal à partir de fichiers image.
Cependant, les capacités des terminaux varient considérablement. Certains terminaux ne prennent en charge que l’ANSI 16 couleurs de base. D’autres prennent en charge le mode 256 couleurs, le true color 24 bits complet, les graphiques SIXEL ou le protocole graphique Kitty, qui peut rendre de véritables images en pixels à l’intérieur du terminal plutôt que des approximations de caractères. La gestion de la largeur Unicode diffère également entre les terminaux, de sorte que les caractères Braille ou larges peuvent se désaligner selon l’environnement.
Conclusion
Que vous écriviez un moteur de rendu ASCII JavaScript pour un navigateur ou que vous acheminiez des données d’image via un outil de terminal, la logique sous-jacente est identique : les pixels deviennent des caractères, la luminosité devient de la densité, et la couleur devient des codes d’échappement ou du CSS. Le navigateur vous donne un contrôle précis sur les polices et la mise en page, tandis que le terminal vous donne vitesse et composabilité. Le choix de l’environnement façonne l’outillage, mais le pipeline de conversion — échantillonner, mesurer, associer, rendre — reste le même.
FAQ
La plupart des caractères de police monospace sont plus hauts que larges, donc chaque cellule de caractère n'est pas un carré parfait. Cet étirement vertical déforme l'image. Vous pouvez compenser en ajustant le line-height en CSS, en redimensionnant l'image source à un rapport d'aspect non carré avant la conversion, ou en échantillonnant moins de lignes par rapport aux colonnes.
Ordonnez les caractères par leur densité visuelle, du plus clair au plus sombre. Une palette plus longue vous donne plus de niveaux de nuances et des dégradés plus lisses. Testez votre palette en rendant une image en dégradé et en vérifiant les bandes visibles. Les éléments de bloc Unicode et les motifs Braille offrent une granularité plus fine que les caractères ASCII standard.
Oui. Dans le navigateur, dessinez chaque trame vidéo sur un canvas hors écran, lisez les données de pixels et associez les cellules aux caractères à chaque trame d'animation. Pour des performances acceptables à 30 fps, gardez la résolution de la grille de caractères modeste ou déléguez le calcul de luminosité à un shader WebGL. Des outils de terminal comme Chafa prennent également en charge l'entrée vidéo.
Les caractères Braille sont Unicode et leur largeur de rendu dépend de l'émulateur de terminal et de la police active. Certains terminaux les traitent comme des caractères larges, d'autres comme des caractères étroits. Si votre sortie semble cassée, testez avec un terminal ou une police différente. Des outils comme Chafa détectent les capacités du terminal et ajustent leur mode de sortie en conséquence.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.