# Programmation objet et géométrie/Objets en Python sous Gimp/Programmation JavaScript sous ImageJ

ImageJ est, lui aussi, un logiciel de traitement d'images, dans lequel les images sont des tableaux de pixels. Mais il est écrit en Java, donc multiplateforme, et possède des fonctionnalités de statistiques très poussées, ce qui renforce son utilité en mathématiques. Et, outre un langage de macros proche de Java (donc objet), son interface de scripts est Rhino qui permet donc de le programmer en JavaScript...

# JavaScript sans image

Pour afficher un résultat (par exemple le contenu d'une variable), on écrit print (en minuscules) suivi, entre parenthèses, du nom de la variable à afficher. Par exemple, on souhaite trouver une expression donnant la somme des carrés des entiers jusqu'à n, en fonction de n. Pour cela, on peut profiter de l'outil d'interpolation d'ImageJ, et créer un tableau en JavaScript, contenant une dizaine de valeurs de cette somme. Plus précisément, ImageJ a besoin de deux tableaux, l'un pour les valeurs de x, l'autre pour les valeurs de y. Voici le script (la variable s contient les valeurs successives de la somme):
Remarque: Bien qu'il ait l'air itératif, le script ci-dessus est basé sur la récursivité, puisqu'il utilise le fait que $\sum _{i=0}^{n}i^{2}=n^{2}+\sum _{i=0}^{n-1}i^{2}$ (ligne 5).
Sous ImageJ, on doit ouvrir une console par Plugins>New>JavaScript puis y taper le script ci-dessus. Ensuite le raccourci clavier Control+R lance le script, ce qui a pour effet d'ouvrir une fenêtre dans laquelle se trouve un tableau, donnant en première colonne les entiers successifs, et en deuxième colonne les valeurs successives de la suite. Ce tableau est exactement ce dont l'outil Curve Fitting d'ImageJ a besoin. Il suffit alors de copier ce tableau (Control+A puis Control+C) puis de le coller dans l'outil en question (accessible par Analyse>Tools>Curve Fitting qui crée un tableau où il faut remplacer les données actuelles par celles créées par JavaScript). Après choix du polynôme de degré 4 (tâtonnements précédents ou intuition), on obtient ceci:
L'image porte assez d'informations pour qu'on voie que l'expression est exacte (parce que le carré du coefficient de régression est égal à 1), polynomiale (on l'a choisie telle), de degré 3, et ayant x comme facteur. Il ne reste alors plus qu'à reconnaître des fractions dans les coefficients, puis à effectuer la factorisation, par exemple avec un logiciel de calcul formel, mais ceci est une autre histoire...

# création d'images en JavaScript
## Lignes de niveau

L'objet le plus important, c'est ImageJ lui-même, appelé IJ en JavaScript. Pour dessiner, il faut un chevalet, en l'occurence une image blanche, où on va placer des pixels, qui sera en couleurs (RGB) et fera 400 pixels par 400. La méthode createImage de l'objet IJ s'en charge. On peut en fait considérer l'objet dessin ci-dessous comme une instance de la classe IJ. Mais ce n'est pas fini! Il faut ensuite créer un objet (instance de la classe image processor) qui hérite des filtres d'ImageJ. Ce qui se fait en invoquant la méthode getProcessor de l'objet dessin (qui hérite cette méthode d'ImageJ).
Enfin pour que l'image apparaisse à l'écran, il faut la mettre à jour (transférer son contenu dans une partie de la mémoire qui soit visible à l'écran), avec dessin.show qui est une méthode que l'objet dessin a héritée de sa classe mère (IJ).

### Fonction de deux variables

Puisqu'on travaille dans des coordonnées entières (numéros des pixels), on va représenter par ses lignes de niveau, la fonction pgcd(x,y) qui est elle-même entière. Dans la boucle sur l'abscisse i, on a placé un rectangle (méthode showProgressBar de l'objet IJ, affiché en bas à droite dans la console ImageJ) qui affiche la progression du programme, ce qui permet de voir quelle partie de l'image occupe le plus de temps de calcul. En mode RGB, les couleurs sont indiquées par des entiers longs, dont le reste modulo 256 indique la quantité de bleu. Donc une valeur nulle représente du noir, une valeur 255 du bleu clair, une valeur 255*256 du vert clair, et une valeur 255*256*256 du rouge clair. En multipliant le pgcd par 256*256, on obtient une valeur de rouge d'autant plus claire que le pgcd est élevé. Mais lorsque celui-ci dépasse 255, il est de nouveau représenté par une valeur sombre (visible en bas de la diagonale ci-dessous). Le script pour représenter en rouge les pgcd des nombres de 0 à 399 est ici:
Comme il y a beaucoup de nombres premiers entre eux, l'image obtenue est sombre:

### Représentation dans l'espace

ImageJ permet aussi de convertir une surface donnée par ses lignes de niveau comme ci-dessus, en une représentation graphique sous forme d'une surface dans l'espace. De même que ci-dessus, on va donc créer une image où les niveaux de gris représentent une fonction $z=f(x,y)$ et la faire convertir par ImageJ en dessin de la surface correspondante, vue en perspective. La fonction $z=f(x,y)$ considérée est la somme des distances entre le point de coordonnées (i,j) et les points de coordonnées respectives A(200;50), B(100;350) et C(350;350) (Attention: L'axe des y est orienté vers le bas). On sait depuis Fermat et Torricelli que cette fonction atteint son minimum en un point appelé point de Fermat-Torricelli du triangle dont les sommets sont donnés ci-dessus.
Comme on fait de la géométrie, il est assez efficace de créer des objets point et triangle qui vont considérablement simplifier le code JavaScript (avec des méthodes adéquates) qui suivra. Tout d'abord, l'objet point ne possède que deux propriétés, ses coordonnées, et une méthode, son affichage. On a besoin d'une fonction distance (entre deux points) et d'une procédure triangle (ayant pour variables ses trois sommets):
On note A.x l'abscisse de A (x est une propriété de l'objet A). La création de l'image se fait comme ci-dessus, avec la méthode createImage de l'objet IJ. On obtient alors un objet plan qui est une image (le chevalet initialement blanc). La méthode getProcessor permet alors d'avoir les filtres de cet objet (flou, Voronoi etc.). Ce processeur ne servira ici que pour ses méthodes de tracé de pixel et de segments (le triangle):
L'exécution du script produit alors l'image suivante:
Comme c'est une image en noir et blanc, ImageJ permet automatiquement de tracer la surface, avec Analyse>Surface Plot:

## Dessin de fractales

Tout ce qui précède peut servir à construire des images fractales en JavaScript:

### Sierpinski
#### Version itérative

Le triangle de Sierpinski, version IFS, est placé dans un objet appelé flocon, qui est une instance de la classe image:
Le fichier obtenu est celui-ci (en quelques secondes):

#### Version récursive

On peut aussi utiliser l'objet triangle utilisé ci-dessus pour dessiner le triangle de Sierpinski comme un polygone. Seulement on aura besoin non pas de la distance entre deux points, mais de leur milieu (un point):
Avec ces objets, la définition récursive du polygone de Sierpinski est assez courte:
Pour obtenir le dessin, il suffit d'appeler la fonction sierpinski ci-dessus avec les trois points A, B et C et l'ordre 6 (à l'ordre 0, seul un triangle est tracé; en fait à l'ordre $n$ il y a exactement $3^{n}$ triangles):
L'image obtenue est incontestablement un triangle de Sierpinski:
Comme le triangle ci-dessus est en noir et blanc, on peut utiliser la méthode statistique Fractal Box Count d'ImageJ pour estimer sa dimension fractale. Le diagnostic d'ImageJ est alors celui-ci:
La valeur exacte ${\frac {\log 3}{\log 2}}\approx 1,585$ est légèrement supérieure à celle estimée par ImageJ. Ce biais est sans doute dù à ce que les détails les plus fins se fondent dans les pixels. Refaire le tout avec une plus grande résolution est également laissé en exercice.

### Julia

Une double boucle parcourant tous les pixels permet de dessiner un ensemble de Julia par balayage (méthode moins rapide que l'itération inverse mais plus colorée). Le script permettant de dessiner l'ensemble de Julia de $z\mapsto z^{2}+i$ ci-dessous (x allant de -1 à 1 et y aussi) est laissé en exercice.
En voyant cette image, comment ne pas avoir le coup de foudre pour les ensembles de Julia?

### Mandelbrot

La même méthode permet de dessiner l'ensemble de Mandelbrot en donnant à chaque pixel une couleur proportionnelle au nombre d'itérations qu'il a fallu pour que le terme de la suite $z_{0}=c$, $z_{n+1}=z_{n}^{2}+c$ sorte du disque de centre l'origine et de rayon 2. Comme précédemment, on crée une image cardio qui est un objet, une instance de la classe IJ, et on y place l'un après l'autre des pixels dont la couleur est calculée dans une boucle:
En observant la barre de progrès, on constate que la partie gauche de l'ensemble de Mandelbrot est beaucoup plus rapide à calculer que la partie droite. Ce phénomène illustre la notion de vitesse de divergence.