Avec Zupple, team building et jeux de piste à Lyon, nous sommes partenaire du RAIDinLyon. Dans le cadre du prochain événement, on nous a demandé s’il était possible de pixeliser une image dynamiquement. C’est à dire avoir une image plus ou moins pixelisée en fonction des réponses des joueurs et joueuses. Et chez Zupple, on adore les défis !
Mon petit exercice du week-end a donc été de pixeliser une image avec JavaScript, et c'était plus facile que ce à quoi je m'attendais !
Voici une démonstration de ce que je voulais coder. Mon objectif était de pouvoir décider à la volée du niveau de pixelisation. Si vous déplacez le curseur qui se trouve sur l'image, vous pourrez donc rendre l'image de plus nette ou plus floue !
Pour réaliser une image pixelisée, la technique est de dessiner une image plus petite puis de l'étirer à sa taille originale.
Pour que ça fonctionne, il faut demander au canvas de ne pas lisser le rendu quand il étire l'image réduite. Cela
nous permettra d'obtenir de grands pixels bien nets. L'option à définir pour décider si l'on veut ou
non lisser le rendu est ctx.imageSmoothingEnabled
.
// Demande au contexte de rendu du canvas de ne pas lisser les images
ctx.imageSmoothingEnabled = false;
La méthode drawImage()
permet de dessiner une image dans un contexte de rendu 2D d'un canvas. La plupart du temps
on l'utilise avec seulement 3 paramètres : l'image et les coordonées où la dessiner. Pour réaliser
notre image pixelisée, nous devrons utiliser des appels avec 5, puis 9 paramètres.
/** drawImage() avec 3 paramètres
* - Prend l'image source
* - Dessine la dans le canvas aux coordonnées destX / destY
*/
ctx.drawImage(image, destX, destY);
/** drawImage() avec 5 paramètres
* - Prend l'image source
* - Redimensionne la à la taille destL / destH
* - Dessine la dans le canvas aux coordonnées destX / destY
*/
void ctx.drawImage(image, destX, destY, destL, destH);
/** drawImage() avec 9 paramètres
* - Prend l'image source
* - Garde une zone de taille sourceL / sourceH aux coordonnées sourceX / sourceY
* - Redimensionne la à la taille destL / destH
* - Dessine la dans le canvas aux coordonnées destX / destY
*/
void ctx.drawImage(
image,
sourceX,
sourceY,
sourceL,
sourceH,
destX,
destY,
destL,
destH
);
Première étape, dessiner une image plus petite :
/**
* Dessine une image plus petite
*
* @param {HTMLImageElement} img - image source
* @param {number} ratio - le ratio de réduction de l'image
* @returns {HTMLCanvasElement}
*/
function reduceImage(img, ratio) {
// Initialisation d'un nouvean canvas
const canvas = document.createElement("canvas");
// On définit la taille intrinsèque du canvas avec des dimensions réduites
canvas.width = img.naturalWidth / ratio;
canvas.height = img.naturalHeight / ratio;
// Récupération du contexte de rendu
const ctx = canvas.getContext("2d");
// On dessine l'image sur toute la taille du canvas
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
return canvas;
}
Deuxième étape, on dessine une nouvelle image. Cette fois-ci aux dimensions initiales mais à partir de la version réduite :
/**
* Pixelise une image dans un canvas
*
* @param {HTMLCanvasElement} canvas - canvas où l'on va dessiner l'image pixelisée
* @param {HTMLImageElement} img - image source
* @param {number} ratio - le ratio de réduction de l'image
* @returns {void}
*/
function pixelateImage(canvas, img, ratio) {
// On définit la taille intrinsèque du canvas avec les dimensions d'origine
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// Paramètrage du contexte de rendu pour ne pas lisser les pixels
const ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
// On dessine une image plus petite
const smallCanvas = reduceImage(img, ratio);
// On étire l'image réduite sur toute la taille du canvas
ctx.drawImage(
smallCanvas,
0,
0,
smallCanvas.width,
smallCanvas.height,
0,
0,
canvas.width,
canvas.height
);
}
En utilisant la fonction ci-dessus, vous pouvez recréer des images avec des effets pixelisés !