Web workers — Canvas

Master Internet, Données et Connaissances

Alexandre Niveau

Enseignement des technologies du Web

 

Web workers — Canvas

Notes de cours

Travail personnel

Objectifs

Le premier exercice est une application directe des web workers pour constater leur intérêt en pratique. Dans le deuxième, on utilise le canevas pour manipuler des images, et on mélange ça avec les web workers et l'API File.

Exercice 1 — Nombres premiers #

On utilise un prétexte simple pour manipuler un peu les web workers : une appli qui calcule le n-ième nombre premier. Par exemple le premier nombre premier est 2, le deuxième est 3, le troisième est 5, etc.

  1. Créer une page avec deux formulaires, qui vont nous servir à tester avec ou sans workers. Chaque formulaire doit contenir un input (pour un nombre), un output et un bouton.
  2. Écrire une fonction is_prime(z) qui teste si le nombre entier z donné est premier. Ne pas viser l'efficacité ! L'objectif ici est de tester des fonctions qui prennent du temps à s'exécuter de toute façon…
    On pourra copier le code suivant pour aller plus vite :
    function is_prime(nb) {
    	for (let i = 2; i <= Math.sqrt(nb); i++) {
    		if (nb % i == 0) {
    			return false;
    		}
    	}
    	return true;
    }
    
  3. Écrire une fonction nth_prime(n) qui retourne le n-ième nombre premier (comme expliqué plus haut). On utilisera évidemment la fonction précédente, et on ne cherchera pas à faire quelque chose de malin !
    On pourra copier le code suivant pour aller plus vite :
    function nth_prime(n) {
    	let current = 1
    	for (let i = 0; i < n; i++) {
    		do {
    			current++;
    		} while (! is_prime(current));
    	}
    	return current;
    }
    
  4. Faire en sorte que le premier formulaire calcule le n-ième nombre premier dans son output, avec n l'entier donné en input par l'internaute.
  5. Donnez un input suffisamment grand pour que le calcul prenne du temps ; en fonction de la machine et de votre implémentation, avec un n de l'ordre de 100 000 ça devrait déjà être pas mal (augmentez progressivement pour que le calcul prenne au moins quelques secondes). Constater que l'UI de la page n'est pas utilisable du tout.
  6. Utiliser un web worker pour que le second formulaire fasse le même calcul, mais dans un autre thread (et potentiellement, en fonction de la machine, dans un autre cœur). Constater que l'UI de la page reste majoritairement utilisable.
    Attention, les navigateurs peuvent mettre en cache le script exécuté par les workers, et ne pas le mettre à jour lors d'un rafraîchissement de la page, ce qui est très ennuyeux lors du développement. Si vous rencontrez le problème, une solution simple est d'ajouter à l'URL du script un paramètre bidon qui change à chaque appel, afin de forcer le téléchargement malgré le cache. On pourra utiliser par exemple "worker.js?v=" + new Date().getTime(). (On enlèverait évidemment ce paramètre sur un site en production.)
  7. Optionnel : ajouter une progressbar indiquant la progression du calcul.

Exercice 2 — Éditeur d’images #

On va créer un début d'application de traitement d'image.

Les bases : manipulation des pixels de l'image

  1. Créer une page avec une image et un canevas.
  2. Dessiner l'image dans le canevas. La page doit maintenant présenter deux images identiques.
  3. Inverser les couleurs de l'image dans le canevas.
  4. Au lieu d'inverser les couleurs directement au démarrage de la page, ajouter un bouton qui permette de le faire à la demande.

Délégation du travail à un thread

Normalement, le traitement de l'image n'est pas instantané : essayer avec une image relativement grosse (quelques mégaoctets). Il est donc pertinent de déléguer ce travail à un worker.

Mettre en place un worker qui récupère les données de l'image, travaille dessus, et renvoie le résultat. Il va falloir utiliser le transfert d'objet, pour éviter de copier les données entre le script et le worker.

Édition d'une image fournie par l'internaute

On va maintenant rendre notre page plus interactive.

  1. Enlever l'image, et mettre à la place un champ d'upload de fichier, qui va permettre à l'internaute de manipuler ses propres images.
  2. Lors de la sélection d'un fichier par l'internaute, s'il s'agit d'une image, elle doit se dessiner dans le canevas. NB : le moyen le plus simple est de créer un img en JS et de procéder comme précédemment (sauf que l'élément img n'apparaîtra pas sur la page).

Optionnel : amélioration de l'éditeur

Ajouter trois sliders R, G, B, avec des valeurs de 0 à 255, et les utiliser pour créer un effet de seuil ou d'écrêtage : la valeur du canal R de chaque pixel n'est gardée que si elle est supérieure au seuil, sinon elle est mise à 0 (ou à 255, ou au seuil, au choix).