Pourquoi un minuscule JPEG peut changer d’aspect dans Chrome
Un détail de rendu apparemment anodin cache en fait une optimisation profonde de la pile image de Chrome. Quand un JPEG est affiché très petit, le navigateur peut en décoder directement une version réduite, plus rapide et moins coûteuse en mémoire, au prix d’un rendu parfois différent.
Fil « Rendu des très petits JPEG dans Chrome »
Publié le 3 août 2026, l’article de Guillaume Técher part d’un cas concret : un logo JPEG affiché à 15 pixels n’avait pas le même aspect dans Firefox et dans Chrome. Son enquête montre que Chrome ne fait pas toujours « décoder l’image complète puis la réduire ». Pour les JPEG, le navigateur délègue à Skia (la bibliothèque graphique de Chrome, chargée du dessin) et Skia s’appuie sur libjpeg-turbo (une bibliothèque de décodage JPEG optimisée) pour utiliser un mode de décodage réduit quand la taille cible est très petite. (guillaumetech.github.io)
Ce qui se passe techniquement
Le point clé est la structure même du JPEG. Le format découpe l’image en blocs de 8 × 8 pixels et applique une DCT (Discrete Cosine Transform, une transformation qui représente l’image sous forme de fréquences visuelles). Quand on réduit fortement une image, on perd surtout les hautes fréquences — autrement dit les détails fins, les contours subtils et les micro-variations de texture. L’article illustre l’idée avec un arbre : en très petit, il ne reste plus qu’une masse verte et un tronc brun, les détails des feuilles disparaissant presque complètement. (guillaumetech.github.io)
Au lieu de reconstruire toute l’image, Chrome peut donc demander un décodage partiel en s’appuyant sur l’IDCT partielle (Inverse Discrete Cosine Transform, retour des fréquences vers les pixels sans tout recalculer). L’article explique qu’à un huitième de l’échelle, un bloc 8 × 8 peut se résumer à un seul pixel, ce qui permet d’ignorer une partie des coefficients de fréquence. Résultat : moins de mémoire utilisée et un décodage plus rapide. L’exemple donné est parlant : un JPEG de 2000 × 2000 pixels occupe environ 12 Mo une fois décompressé, alors qu’une image finale de 20 × 20 pixels ne demande qu’environ 1,2 Ko. (guillaumetech.github.io)
Pourquoi Chrome n’affiche pas exactement la même chose
Dans les lignes citées par l’auteur, Skia/libjpeg-turbo calcule une échelle de décodage compatible avec les blocs DCT, puis applique ensuite un redimensionnement plus classique pour atteindre la taille exacte voulue. Le code de libjpeg-turbo montre bien cette logique avec des paliers de sortie calculés à partir de scale_num, scale_denom et de DCTSIZE (la taille standard d’un bloc JPEG, ici 8), ce qui confirme que la bibliothèque sait produire des images déjà réduites au moment du décodage. L’auteur a ajouté une correction datée du 12 août 2026 : la différence visuelle ne vient pas uniquement de l’IDCT partielle, mais aussi de l’algorithme de redimensionnement appliqué ensuite. (guillaumetech.github.io)
Ce que ça change concrètement pour un développeur web
La leçon pratique est simple : n’utilisez pas JPEG pour des icônes, logos minuscules ou éléments d’interface. Le JPEG est pensé pour les photographies, pas pour les formes nettes, les aplats ou les petits visuels d’interface. Si vous avez déjà vu un pictogramme paraître plus épais, plus flou ou légèrement différent selon le navigateur, ce n’est pas forcément un bug CSS : cela peut venir de la chaîne de décodage d’image. Pour les petits assets, privilégiez SVG (vectoriel, donc net à toutes tailles) ou, si nécessaire, un bitmap sans perte adapté à la taille réelle d’affichage. (guillaumetech.github.io)
Un rappel utile côté implémentation : si un visuel d’interface est déjà livré dans un format fragile à la réduction, aucun width/height ou style CSS ne corrigera le problème de fond. Le bon correctif est souvent de changer de format ou de fournir une ressource conçue pour sa taille cible.
<img src="/logo.svg" width="15" height="15" alt="Logo">
« Really, the moral here is that you should not use JPEG for icons and the like. » (guillaumetech.github.io)