Support de cours modifier les éléments multimédias HTML5 en JavaScript, tutoriel & guide de travaux pratiques HTML5 en pdf.
Listing 7.3 : Web Worker JavaScript du Listing 7.2
onmessage = function (event) {
// Récupérer les données d’image var data = event.data;
var frame = data.frame; var h = data.height; var w = data.width; var x,y;
// Parcourir en boucle chaque pixel de l’image for (x = 0; x < w; x ++) {
for (y = 0; y < h; y ++) {
// Index dans l’image i = x + w*y;
// Récupérer les couleurs r = frame.data[4*i+0];
g = frame.data[4*i+1]; b = frame.data[4*i+2];
// Remplacer par les couleurs sépia
frame.data[4*i+0] = Math.min(0.393*r + 0.769*g + 0.189*b, 255); frame.data[4*i+1] = Math.min(0.349*r + 0.686*g + 0.168*b, 255); frame.data[4*i+2] = Math.min(0.272*r + 0.534*g + 0.131*b, 255); }
}
// Retransmettre les données d’image au thread principal postMessage(frame);
}
Nous avons là un bon exemple de manipulation d’une vidéo avec un Web Worker. On ne peut pas transmettre un canevas directement à un Web Worker, par exemple comme paramètre de la fonction postMessage(), car il s’agit d’un élément du DOM, alors que les Web Workers ne reconnaissent pas les éléments du DOM. En revanche, vous pouvez passer les données d’image au Worker. La méthode pour manipuler une vidéo consiste donc à récupérer une image vidéo avec getImageData(), à la placer dans un message et à transmettre ce message au Web Worker avec postMessage(), où l’événement message déclenche l’exécution de l’algorithme de manipulation de la vidéo. Le résultat des calculs est renvoyé au thread principal par le Web Worker via un appel postMessage() avec les données d’image manipulées en paramètre. Le contrôle est ainsi redonné au gestionnaire d’événements onmessage du thread principal afin d’afficher l’image manipulée en utilisant putImageData() dans le canevas.
Les Web Workers sont pris en charge dans tous les navigateurs à l’exception d’Internet Explorer. Le résultat de l’implémentation avec Web Workers de l’exemple de conversion en tons sépia est identique à celui de l’implémentation sans Worker (voir Figure 7.1).
Si vous réalisez vos développements sous Opera et que vous comptiez recharger votre Web Worker en effectuant un rechargement de la page web avec la touche Maj enfoncée, vous risquez d’être déçu. Assurez-vous donc de conserver un onglet supplémentaire ouvert avec un lien vers le fichier JavaScript du Web Worker et effectuez séparement le rechargement des deux pages.
L’exemple sépia est simple, si bien qu’on peut légitimement se demander si la surcharge résultant de la préparation du message (copier les données du message, en incluant l’image), son dépaquetage et ces opérations reproduites pour le résultat ajoutées au délai d’appel des événements, ne surpasse pas finalement le gain de temps obtenu en déléguant la manipulation des données vidéo à un thread.
Il faut comparer le nombre d’images manipulées lors de l’exécution dans le thread principal avec le nombre d’images qu’un Web Worker traite pour déterminer les limites de cette approche. Notez que cette méthode est limitée par l’obligation que nous nous imposons de conserver l’affichage du Web Worker et la lecture de la vidéo approximativement synchronisés au lieu d’autoriser le Web Worker à être plus lent. Le Tableau 7.1 présente le résultat avec le nombre d’images traitées pour la vidéo d’exemple Hello Word de quatre secondes.
Nous avons obtenu les résultats du Tableau 7.1 sur un même ordinateur, avec une charge identique, en rechargeant l’exemple plusieurs fois et en enregistrant le nombre maximal d’images recolorées atteint par chaque navigateur. Notez que l’algorithme avec Web Workers traite moins d’images sur Firefox et Chrome que lorsque le code est exécuté sur la page web principale. Pour Safari, il y a un gain de vitesse, alors qu’Opera présente à peu près les mêmes performances avec ou sans Web Worker.
Ces résultats semblent dépendre de la manière dont les navigateurs implémentent la prise en charge des Web Workers. Notez que nous ne comparons pas les perfor-mances entre les différents navigateurs, qui dépendent clairement de leurs moteurs JavaScript, mais on peut voir l’effet combiné de la manière dont chaque navigateur implémente les Web Workers et de la vitesse de son moteur JavaScript.
Opera est conçu comme un navigateur à thread unique, aussi son implémentation actuelle de Web Workers intercale-t-elle l’exécution du code dans le thread unique. L’implémentation Mozilla dans Firefox est différente, puisque le Web Worker est un véritable thread de système d’exploitation et que la division des workers permet de tirer parti des multiples cœurs de processeur. La surcharge introduite par le fait de générer un thread de niveau système complet dans notre simple exemple ici semble avoir un impact négatif sur le nombre d’images qui peuvent être décodées et transmises depuis le thread principal durant le temps de lecture.
Le principal avantage de l’utilisation d’un Web Worker tient à ce que la surcharge du thread principal est réduite de telle sorte qu’il peut continuer à s’exécuter à pleine vitesse. En particulier, il peut ainsi continuer d’afficher l’interface utilisateur du navigateur, de vérifier vos e-mails, etc. Dans notre exemple, cela se manifeste particulièrement par la vitesse de lecture de la vidéo. Dans l’exemple de la conver-sion en tons sépia, notre thread principal n’était pas particulièrement surchargé de calculs, aussi l’introduction des Web Workers n’a-t-elle pas apporté d’amélioration importante. Passons donc maintenant à un exemple plus musclé.
Détection de mouvement avec des Web Workers
L’idée générale de la détection de mouvement consiste à considérer la différence entre deux images successives dans une vidéo et à déterminer s’il existe un chan-gement suffisamment important pour conclure qu’il s’agit d’un mouvement. Les bons détecteurs de mouvement peuvent gérer les changements de conditions lumi-neuses, les caméras qui se déplacent et les artéfacts de caméra et d’encodage. Pour notre exemple, nous allons simplement déterminer si un pixel a changé afin de savoir s’il y a eu un mouvement. C’est une approche simple mais plutôt efficace qui conviendra pour les besoins de la démonstration.
Niveaux de gris
L’approche pratique de la détection de mouvement implique de prétraiter les images en les passant en niveaux de gris. Comme la couleur n’influence pas le mouve-ment, c’est une abstraction raisonnable, qui réduit le nombre de calculs nécessaires, puisque les différences n’ont pas besoin d’être calculées sur toutes les couches, mais uniquement sur une seule.
On réalise le passage en niveaux de gris en calculant la luminance (l’intensité lumi-neuse) de chaque pixel et en remplaçant les valeurs des couches rouge, vert et bleu par cette valeur de luminance. Toutes les couches possédant alors des valeurs iden-tiques, l’image n’a plus de couleur et apparaît en gris.
On peut calculer la luminance à partir d’une moyenne des valeurs originales rouge, vert et bleu, mais cette méthode ne concorde pas avec la perception humaine de la luminance. En réalité, le meilleur moyen de calculer la luminance consiste à prendre 30% de rouge, 59% de vert et 11% de bleu1. Le bleu est perçu comme une couleur très sombre et le vert comme une couleur très claire, de sorte que ces deux couleurs contribuent différemment à la perception humaine de la luminance.
Le Listing 7.4 présente le Web Worker JavaScript qui crée une version en niveaux de gris de la vidéo à l’aide de cet algorithme. Le code du thread principal associé à ce Web Worker est identique à celui du Listing 7.2. La Figure 7.2 présente les captures d’écran résultant des différents navigateurs. La vidéo du haut est en couleur et le canevas en dessous est en noir et blanc.
……….