Par l'équipe Codermind. |
Question
«J'ai créé un fichier image sous Photoshop contenant un texte en noir sur blanc. Ce texte est correctement antialiasé lorsque je le l'utilise sous forme de texture dans mon programme. Par contre lorsque j'inverse les couleurs en transformant le noir en blanc et vice et versa, le résultat est un texte qui a des effets d'escalier (aliasing) prononcés. Qui peut m'expliquer ce résultat assez incompréhensible ?»
Réponse
Il s'agit d'un artefact lié au fait que l'espace d'affichage par défaut de Windows n'est pas en linéaire/perceptuel, la rampe qui lie la valeur rgb à l'intensité perçue n'est pas lineaire. Windows comme d'autres OS et les standards conçus pour le world wide web, définissent l'espace sRGB comme espace d'affichage par défaut. L'espace sRGB est une forme simple de compression d'information qui donne une plus grande précision aux informations dans les basses intensité. En se basant sur le fait que l'oeil humain est plus sensible aux variations de teinte dans les basses intensités.
Un fichier image dans un OS et avec un moniteur bien calibré aura donc la valeur de gris intermédiaire à 186/255 plutot qu'à 127.5/255.
Il faut donc que l'outil d'anti-aliasing de police écran en tienne compte (c'est le cas de Photoshop par exemple quand tu utilises ses fontes antialiasées dans l'espace de travail par défaut) et surtout que tu ne fasse pas d'opération non linéaire sur la texture finale. L'inversion que tu as pratiquée dans ton application est un type classique d'opération non linéaire. La linéarité doit être dans l'espace perceptif (de ton oeil) et pas l'espace sRGB intermédiaire. En effet, l'anti-aliasing repose sur le fait que une intensité linéaire de 50% peut-être simulée par une couverture en pixel de 50% et vice et versa. Donc dans ta situation lorsque tu as cette couverture de 50%, tu vas l'encoder comme une valeur de gris à 50%. Cette valeur de gris va être convertie dans l'espace sRGB, pour devenir 73%. Si tu l'inverses telle quelle dans un pixel shader cette valeur va donc devenir 27%. Mais cette valeur est également dans l'espace sRGB, donc au final ton oeil va estimer une couverture à 6% !
Ton processus a donc introduit une double erreur, une première fois lors de l'encodage en évaluant mal les conditions de restitution et une deuxième fois lors de l'affichage (bien que les deux soient liées bien entendu). Restituer une inversion en mode linéaire, en partant du principe que l'image de départ a été calculée en sRGB se fait de la manière suivante : conversion sRGB vers linéaire, inversion, linéaire vers sRGB.
Une autre option est de forcer ton logiciel à travailler dans un espace linéaire et à stocker le fichier au format linéaire (où 50% d'intensité sont stockés sous une valeur proche de 127.5/255). Tu ne peux par contre pas totalement échapper à la conversion finale de linéaire vers sRGB. Bien entendu si tu omets cette dernière partie (pour manque de support hardware) le résultat sera un peu moins moche que dans ta situation initiale (simple erreur au lieu de double erreur).




