Appearance
Le tableau pixels[]
Cette page reprend à la fois les méthodes pour afficher les images et celles permettant d'accéder au pixels mêmes d'une image et de les modifier en fonction de telle ou telle condition.
Pixels
Une image numérique n'est rien de plus que des données - des nombres indiquant des variations de rouge, vert et bleu à un endroit particulier sur une grille de pixels. La plupart du temps, nous considérons ces pixels comme des rectangles miniatures pris en sandwich sur un écran d'ordinateur. Cependant, avec un peu de réflexion créative et une manipulation de niveau inférieur des pixels avec du code, nous pouvons afficher ces informations d'une multitude de façons.
Dan Shiffman sur le site de Processing.
Source de l'image: https://medium.com/inside-vbat/anni-albers-fd3254325c92
Charger et afficher une image dans votre sketch
Une image se charge dans votre sketch en 3 étapes:
- Initialiser une variable de type PImage (Crée une instance de la classe PImage)
- Charger l'image dans cette variable à l'aide de la fonction loadImage()
- Utiliser l'image ou l'afficher simplement
js
// PROCESSING
PImage img; // Déclaration de la variable image
void setup() {
size(1000, 520);
img = loadImage("anni.png"); // Chargement de l'image dans la variable
}
void draw() {
image(img, 0, 0); // Affichage de l'image
}TIP
Note: Processing accepte les formats de fichiers GIF, JPG, TGA, PNG pour les images.
Une fois chargée, l'image peut être utilisée comme outil de dessin, comme on pouvait le faire avec une ellipse ou une ligne.
js
// PROCESSING
PImage img;
void setup() {
size(1000, 520);
img = loadImage("anni.png");
}
void draw() {
if(mousePressed) {
image(img, mouseX, mouseY);
}
}La fonction image()
La fonction image() prend par défaut 3 paramètres. Le premier est l'image elle-même (dans la plupart des cas le nom de la variable). Les deuxième et troisième paramètres correspondent à la position en x et en y de l'image dans l'espace de dessin.
L'ajout de deux paramètres supplémentaires permet de définir une largeur et une hauteur à l'image dans notre sketch.
Pour travailler de façon plus flexible, nous pouvons utiliser les propriétés width et height de l'élément image.
js
// PROCESSING
PImage img;
void setup() {
size(1000, 520);
img = loadImage("anni.png");
}
void draw() {
if(mousePressed) {
image(img, mouseX, mouseY, img.width/3, img.height/3);
}
}Pixels!
Pixels sans 'image'
De temps en temps, il peut être utile pour nous de quitter nos ellipses, rectangles et autres lignes pour nous aventurer un niveau plus bas, au niveau des pixels mêmes de notre espace de travail. Ce sont eux que nous allons manipuler directement (ce que Processing fait en général pour nous, par exemple lorsque nous dessinons une ellipse).
l'exemple ci-dessous redéfini, dans Processing, chaque pixel de notre format en lui assignant une valeur de gris aléatoire, et ce chaque fois que la souris est pressée.
js
// PROCESSING
void setup() {
size(740, 400);
loadPixels();
}
void draw() {
if(mousePressed) {
for(int i=0; i<pixels.length; i++) {
float rand = random(255);
color c = color(rand);
pixels[i] = c;
}
}
updatePixels();
}En général, nous considérons les images comme des grilles de pixels avec une largeur et une hauteur. C'est effectivement ce qui s'affiche sur nos écrans. Cependant la réalité des pixels est légèrement différente. Ils sont en fait stockés sur un seul niveau, comme une liste à une seule dimension donc. Il s'agit d'un tableau (Array) qui peut ressembler à ceci:
Nous pouvons rendre disponible ce tableau dans notre programme à l'aide de la fonction loadPixels().
Nous pouvons ensuite "remplir" notre sketch pixel par pixel à l'aide des boucles for() et en créant notre propre logique.
Pour mettre à jour l'affichage du tableau de pixels, il nous faut également utiliser la fonction updatePixels().
js
// PROCESSING
void setup() {
size(1000, 520);
loadPixels();
}
void draw() {
if(mousePressed) {
for(int i=0; i<pixels.length; i++) {
float rand = random(255);
color c = color(rand);
pixels[i] = c;
}
}
updatePixels();
}Pixels d'une image
La fonction loadPixels() de Processing charge, par défaut, l'ensemble des pixels de l'espace de dessin et les place dans un tableau. Nous pouvons par la suite accéder aux valeurs de rouge, de vert et de bleu de chaque pixel, ainsi qu'à leur teinte, luminosité ou saturation, en utilisant l'index (position) de chaque pixel dans le tableau.
Si votre image a été dessinée auparavant, vous pourrez donc accéder aux données des pixels de cette même image de cette manière. Mais il vous sera plus simple de vous y prendre de cette manière:
js
img.pixels[45] // Pour récupérer la couleur du 46e pixel du tableau, par exemple.De plus, une fois qu'une image est chargée (ligne 5), vous pouvez utiliser ses propriétés width et height pour récupérer largeur et hauteur dynamiquement (voir ligne 9)
js
PImage img;
void setup() {
size(1000, 520);
img = loadImage("anni.png");
}
void draw() {
image(img, mouseX, mouseY, img.width/5, img.height/5);
}js
// PROCESSING
PImage img;
int pointillize = 10;
void setup() {
size(1000,520);
img = loadImage("anni.png");
background(0);
smooth();
rectMode(CENTER);
}
void draw() {
// On définit un point aléatoirement
int x = int(random(img.width));
int y = int(random(img.height));
int loc = x + y*img.width;
// On va chercher les réferences R, V et B du pixel en question dans l'image
loadPixels();
float r = red(img.pixels[loc]);
float g = green(img.pixels[loc]);
float b = blue(img.pixels[loc]);
noStroke();// Pas de contour
fill(r,g,b,100);// Couleur avec opacité réduite (100/255)
rect(x,y,pointillize*3,pointillize);
}Les formules respectives, dans Processing et P5js, pour accéder à l'emplacement d'un pixel particulier dans le tableau des pixels du canvas ou d'une image.
Le tableau pixels[] dans P5.js
Le tableau des pixels dans P5.js fonctionne un peu différemment que dans Processing. Là où processing encapsulait les valeur RGBA dans le pixel lui-même, dans p5.js ces valeurs seront stockées chacune dans des emplacements différents du tableau.
Chaque pixel de l'image occupera donc 4 emplacements dans le tableau des pixels. Un pour sa valeur de rouge, un autre pour sa valeur de vert, un autre pour le bleu et enfin un dernier pour la couche alpha.
Si l'on veut récupérer la valeur de rouge du 2e pixel, nous irons donc à pixels[4].
La valeur de bleu du 3e pixel sera quant à elle à pixels[10]. Etc...
Legofactor
Ci-dessus le post de Margot à propos du travail de Geoffroy Amelot, qui nous inspire cette petite adaptation via Processing. (Comment il s'y prend dans Photoshop pour faire ceci reste un mystère..)
Nous utilisons ici le mode colorimétrique HSB qui nous permet plus facilement d'agir sur la luminosité d'une couleur ou sa saturation sans toucher à sa teinte, ce qui serait beaucoup plus complexe en RVB.
Le mode HSB est déclaré en début de programme (ligne 10). Les trois derniers paramètres indiquent à processing la fourchette de valeur avec laquelle nous désirons coder nos couleurs (ici entre 0 et 100 pour les trois composantes). Souvent, la composante teinte utilise une fourchette de 360 (exemple ici), corrrespondant aux degrés du cercle chromatique. Mais le choix est libre...
js
PImage img;
int nbr = 40;
int cote;
float ombre, dia;
void setup() {
size(1000,520);
img = loadImage("anni.png");
noStroke();
colorMode(HSB,100,100,100);
rectMode(CENTER);
ellipseMode(CENTER);
cote = int(width/nbr);
dia = cote-cote/3;
ombre = cote/25;
for(int y=cote/2;y<height;y+=cote) {
for(int x=cote/2;x<width;x+=cote) {
int pos = x+(y*width);
float h = hue(img.pixels[pos]);
float s = saturation(img.pixels[pos]);
float b = brightness(img.pixels[pos]);
fill(h,s,b-7);
rect(x,y,cote,cote);
fill(h,s,b-25);
ellipse(x-ombre,y-ombre,dia, dia);
fill(h,s,b+10);
ellipse(x+ombre,y+ombre,dia, dia);
fill(h,s,b);
ellipse(x,y,dia, dia);
}
}
}
void draw() {}
void keyPressed() {
save("fargues.jpg");
}





