Créer une image avec un algorithme

L’art est partout, même dans les maths :)

Vous vous demandez des fois comment on peut créer des images avec des algorithmes ? Voyons comment c’est possible avec un exemple :

myImage

Pour dessiner cet astre orbitant autour d’une étoile, on explique « simplement » en plusieurs étapes à l’ordinateur comment dessiner :

  • un carré noir (le fond),
  • une zone jaune de moins en moins dense (l’étoile proche),
  • des points orangés dispersés aléatoirement (les étoiles lointaines),
  • une boule avec un effet d’ombre (l’astre).

Un algorithme, c’est une succession d’instructions que l’on donne à l’ordinateur. Il existe plusieurs langages algorithmiques en informatiques : nous allons aujourd’hui nous servir de JavaScript.

Le fond noir

Le fond noir, c’est juste un rectangle. En JavaScript, quand on créé une image simple de dimension (l, L), on stocke un rectangle noir de largeur l et de longueur L. L’unité de longueur étant simplement le pixel.

Du coup, quand on écrit :

var output = new SimpleImage(320, 320);

On obtient :

myImage(1)

L’étoile proche

Pour l’étoile proche, on tire simplement une droite un peu en diagonale. En partant du bord en bas à gauche, on colore le premier pixel en jaune. On colore ensuite tous les autres jusqu’à la droite en diagonale en demandant à l’ordi d’utiliser un jaune de plus en plus sombre (jusqu’au noir). En JavaScript :

for(var pixel of output.values()){
    pixel.setRed  (1.5*pixel.getY()-pixel.getX());
    pixel.setGreen(1.5*pixel.getY()-pixel.getX());
}

Littéralement, on regarde chaque pixel et lui assigne une valeur jaune dont la coloration va dépendre de sa position sur l’image. Plus le pixel sera en bas et plus le jaune sera vif, plus il sera en haut et plus il sera sombre. De même, plus il sera sur la droite et plus il sera sombre.

Pixel.setRed et setGreen sont des fonctions permettant de choisir les couleurs. Pour faire court, la couleur de chaque pixel est créé à partir d’une combinaison de rouge (Red), vert (Green) et bleu (Blue) dont l’intensité varie de 0 à 255. Un pixel noir aura des valeurs rouge, vert, bleu (R,G,B) de 0,0,0 et un blanc 255,255,255. Le jaune choisi en bas à droite est (255,255,0).

Pour comprendre la petite formule, il faut juste savoir que l’image est représenté par un plan de coordonnées (X,Y) et que le point d’origine (0,0) est le point en haut à gauche.

Donc quand j’écris :

pixel.setRed  (1.5*pixel.getY()-pixel.getX());

je demande d’établir la coloration rouge du pixel à la valeur (1.5*pixel.getY()-pixel.getX()). Pour le point de coordonnées (10, 50), sa valeur Red sera de 1,5*50 – 10 = 65.

Et donc sa valeur (R,G,B) après exécution du code  : (65, 65, 0)

En image :

myImage(4)

Les étoiles lointaines

Pour les étoiles, on va dire à l’ordinateur de mettre des pixels oranges un peu partout. Comment ? C’est simple : on va regarder chaque pixel, un à un, et va tirer un nombre au hasard entre 0 et 1. On va ensuite dire à l’ordi de le colorer en orange si ce nombre est supérieur à 0,995 par exemple. Si on veut plus d’étoile on diminue ce seuil, si on en veut moins on le rapproche de 1. En langage JavaScript ça donne ça :

for(var pixel of output.values()){
 if (Math.random() > 0.995){
        pixel.setRed(255);
        pixel.setGreen(140);
    }
}

Après exécution du code :

myImage(2)En exécutant tout le code depuis le début :

myImage(3)L’astre

Avant d’être une boule, notre astre est un cercle. Un cercle en maths, ce sont les points situés à égale distance d’un point. On va donc choisir un point (ses coordonnées) et colorier en jaune tous les points dans un certain périmètre voulu. Si on prend le point de coordonnées (150,150) et qu’on veut un rayon de 50 (pixels), on écrit :

for(var pixel of output.values()){
    if (dist(pixel, 150, 150)<50){
        pixel.setRed(255);
        pixel.setGreen(255);
    }
}

Après exécution du code :

myImage(5)

Pour faire l’effet d’ombre :

for(var pixel of output.values()){
    if (dist(pixel, 150, 150)<50){
        pixel.setRed(255-4*dist(pixel,100,100));
        pixel.setGreen(255-4*dist(pixel,100,100));
    }
}

C’est le même code sauf que la coloration rouge et verte change. Elle n’est plus simplement 255 mais 255-4*dist(pixel,100,100) avec la fonction dist définie comme suit :

function dist(pixel, x, y){
    var dx=pixel.getX() - x;
    var dy=pixel.getY() - y;
    return Math.sqrt(dx*dx+dy*dy);
}

En français ça veut dire que je pars du point de coordonnées (100,100) sur le cercle et je trace un cercle (encore!) de moins en moins coloré :

En image (sur fond blanc pour y voir mieux) :

myImage(6)

L’image complète

On a plus qu’à mettre ensemble les bouts de codes :

function dist(pixel, x, y){
    var dx=pixel.getX() - x;
    var dy=pixel.getY() - y;
    return Math.sqrt(dx*dx+dy*dy);
}
// start with a blank image
var output = new SimpleImage(320, 320);

for(var pixel of output.values()){
    pixel.setRed  (1.5*pixel.getY()-pixel.getX());
    pixel.setGreen(1.5*pixel.getY()-pixel.getX());
    if (Math.random() > 0.995){
        pixel.setRed(255);
        pixel.setGreen(140);
    }
    if (dist(pixel, 150, 150)<50){
        pixel.setRed(255-4*dist(pixel,100,100));
        pixel.setGreen(255-4*dist(pixel,100,100));
    }
}

Et on retrouve l’image initiale !

myImage(7)

Laisser un commentaire