232 votes

Ce qui ' s la meilleure façon de définir un seul pixel dans un canvas HTML5 ?

L’HTML5 Canvas n’a aucune méthode pour définir explicitement un seul pixel.

Il pourrait être possible de définir un pixel à l’aide d’une ligne très courte, mais ensuite casquettes antialising et ligne risquent d’interférer.

Une autre façon serait de créer une petite `` objet et à l’aide de :

pour mettre en place.

Peut n’importe qui décrivent un moyen fiable et efficace d’y parvenir ?

337voto

Phrogz Points 112337

Il y a deux prétendants:

  1. Créer une image de 1x1 de données, définissez la couleur, et putImageData à la location:

    var id = myContext.createImageData(1,1); // only do this once per page
    var d  = id.data;                        // only do this once per page
    d[0]   = r;
    d[1]   = g;
    d[2]   = b;
    d[3]   = a;
    myContext.putImageData( id, x, y );     
    
  2. Utiliser fillRect() pour dessiner un pixel (il n'y a pas d'aliasing):

    ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
    ctx.fillRect( x, y, 1, 1 );
    

Vous pouvez tester la vitesse de ces ici: http://jsperf.com/setting-canvas-pixel
Sur Chrome le 1x1 les données de l'image est d'environ 10x(!) aussi rapide que d'utiliser fillRect.
Sur Firefox 3.6 l'1x1 est seulement d'environ 1,3 x plus rapide.
Sur Firefox 4.0 b le 1x1 est d'environ 80x(!!) plus lent que d' fillRect.
Ce ralentissement se produit uniquement lorsque l'accélération matérielle est activée, et peut être fixé.

Je recommande l'utilisation de 1x1 données d'image pour une vitesse maximale.

D'autres, plus stupides les alternatives sont:

  • à l'aide de getImageData()/putImageData() sur l'ensemble de la toile, comme indiqué dans les tests, c'est environ 100 fois plus lent que les autres options.

  • création d'une image personnalisée à l'aide de données d'url et à l'aide de drawImage() montrer:

    var img = new Image;
    img.src = "data:image/png;base64," + myPNGEncoder(r,g,b,a);
    // Writing the PNGEncoder is left as an exercise for the reader
    
  • création d'une img ou de toile rempli de tous les pixels que vous voulez et utiliser drawImage() blit juste le pixel que vous voulez à travers. Ce serait probablement très rapide, mais a la limite que vous avez besoin pour pré-calculer les pixels dont vous avez besoin.

Notez que mes tests ne tentez pas de le sauvegarder et restaurer le contexte de canevas fillStyle; cela contribue à ralentir l' fillRect de rendement. Notez également que (en raison des limitations dans le cadre d'essais) je ne suis pas de commencer avec une ardoise propre ou de test exactement le même ensemble de pixels pour chaque test.

24voto

Alnitak Points 143355

Je n'avais pas considéré comme fillRect(), mais les réponses se refusait à moi à l'indice de référence à l'encontre putImage().

Mise de 100 000 au hasard les pixels colorés dans des endroits aléatoires, avec Chrome 9.0.597.84 sur un (vieux) MacBook Pro, prend moins de 100ms avec putImage(), mais près de 900ms l'aide d' fillRect(). (Référence au code http://pastebin.com/4ijVKJcC).

Si, au lieu de choisir une seule couleur à l'extérieur des boucles et juste de l'intrigue que de la couleur à des emplacements aléatoires, putImage() prend 59 ms vs 102ms pour fillRect().

Il semble que la surcharge de la production et de l'analyse d'un CSS spécification de la couleur en rgb(...) syntaxe est responsable de la plupart de la différence.

Mettre brutes valeurs RVB directement dans un ImageData bloc d'autre part nécessite aucune chaîne de la manipulation ou de l'analyse.

7voto

Daniel Points 21

Étant donné que les différents navigateurs semble préférer des méthodes différentes, peut-être il serait judicieux de faire un test plus petit avec les trois méthodes dans le cadre du processus de chargement pour savoir quel est le meilleur à utiliser et l’utiliser ensuite dans toute l’application ?

4voto

sdleihssirhc Points 18791

Qu’en est-il un rectangle ? Que ça doit être plus efficace que la création d’un `` objet.

-1voto

Boing Points 92

Pour compléter Phrogz très approfondie de la réponse, il y a une différence essentielle entre fillRect() et putImageData().
La première utilise le contexte pour attirer plus de par l'ajout d' un rectangle (PAS un pixel), à l'aide de la fillStyle valeur alpha ET le contexte globalAlpha et la matrice de transformation, de la ligne de casquettes etc..
La deuxième remplacer et l'ensemble de l' ensemble de pixels (peut-être un, mais pourquoi ?)
Le résultat est différent comme vous pouvez le voir sur la http://jsperf.com/setting-canvas-pixel


Personne ne veut une de pixels à un moment (ce qui signifie dessin sur l'écran). C'est pourquoi il n'y a pas d'API pour le faire (et à juste titre).
Performance sage, si l'objectif est de générer une image (par exemple, une de ray-tracing logiciel), vous pouvez toujours souhaitez utiliser un tableau obtenu, mais getImageData() qui est optimisé Uint8Array. Ensuite, vous appelez putImageData() une FOIS ou quelques fois par seconde à l'aide de setTimeout/seTInterval.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X