Je travaille avec un Canvas relativement grand dans lequel divers éléments (complexes) sont dessinés. Je veux ensuite sauvegarder l'état du canevas, afin de pouvoir le remettre rapidement à l'état où il se trouve maintenant. J'utilise getImageData pour cela et stocke les données dans une variable. Je dessine ensuite un peu plus de choses sur la toile et je réinitialiserai plus tard le Canvas à l'endroit où il se trouvait lorsque je l'ai sauvé, en utilisant putImageData.Pourquoi putImageData est-il si lent?
Cependant, il s'avère que putImageData est très lent. En fait, il est plus lent que de redessiner tout le Canvas à partir de zéro, ce qui implique plusieurs drawImage couvrant la plus grande partie de la surface, et plus de 40.000 opérations lineTo suivies de traits et de remplissages.
Redessiner le canevas d'environ 2 000 x 5 000 pixels à partir de zéro prend ~ 170ms, l'utilisation de putImageData prend cependant 240ms. Pourquoi est-ce que putImageData est si lent comparé à redessiner le canevas, bien que redessiner le canevas implique de remplir presque la totalité du canevas avec drawImage, puis de remplir environ 50% du canevas avec des polygones en utilisant lineTo, stroke et fill. Donc, fondamentalement, chaque pixel est touché au moins une fois lors du redessin. Parce que drawImage semble être beaucoup plus rapide que putImageData (après tout, la partie drawImage de redessiner le canevas prend moins de 30 ms). J'ai décidé d'essayer de sauvegarder l'état de la toile sans utiliser getImageData, mais en utilisant à la place canvas.toDataURL puis en créant une image à partir de l'URL de données que je collerais dans drawImage pour la dessiner sur le canevas. Il s'avère que toute cette procédure est beaucoup plus rapide et prend seulement environ 35ms à compléter. Alors, pourquoi putImageData est-il tellement plus lent que les alternatives (en utilisant getDataURL ou simplement en redessinant)? Comment pourrais-je accélérer les choses plus loin? Y at-il et si, quelle est généralement la meilleure façon de stocker l'état d'une toile?
(Tous les chiffres sont mesurés à l'aide Firebug à partir de Firefox)
Il serait intéressant si vous pouviez poster une démonstration de votre problème en ligne quelque part. Dans noVNC (http://github.com/kanaka/noVNC) j'utilise putImageData pour beaucoup de tableaux de données d'images de petite et moyenne taille et je ne vois pas de problème de performance avec putImageData. Peut-être que vous êtes confronté à un cas de performance pessimal spécifique qui devrait être bugué. – kanaka
Vous pouvez regarder ici http://www.danielbaulig.de/A3O/ Cela ne fonctionnera pas à 100% si la console firebug est éteinte, alors assurez-vous de l'allumer. La version vérifiée est celle qui utilise putImageData. Vous pouvez le déclencher en cliquant sur n'importe quelle "tuile". Il actualisera le canevas du tampon en utilisant putImageData, puis "mettra en surbrillance" la vignette sélectionnée. Dans a3o_oo.js il y a quelques lignes commentées, qui peuvent être utilisées pour basculer entre l'utilisation de putImageData (current), l'utilisation de getDataURL (les deux lignes mentionnant this.boardBuffer) et le redrawing simple (la ligne drawBoard) de l'espace tampon. –
Bonne question et bonnes solutions. Mais avez-vous déjà découvert la vraie raison pour laquelle putImageData est si lent par rapport à drawImage? – cherouvim