Estoy trabajando con un lienzo relativamente grande donde se dibujan varias cosas (complejas). Luego quiero guardar el estado Canvas ', así puedo restablecerlo rápidamente al estado en que se encuentra ahora en un momento posterior. Yo uso getImageData para esto y almaceno los datos en una variable. Luego dibujo algunas cosas más en el lienzo y luego restableceré el lienzo en el lugar donde estaba cuando guardé su estado, usando putImageData.¿Por qué putImageData es tan lento?
Sin embargo, resulta que putImageData es muy lento. De hecho, es más lento que simplemente volver a dibujar todo el lienzo desde el principio, lo que implica varios DrawImage que cubre la mayor parte de la superficie y más de 40.000 operaciones lineTo seguidas de trazos y rellenos.
Redibujar el lienzo de aproximadamente 2000 x 5000 píxeles desde cero lleva ~ 170ms, usando putImageData, sin embargo, toma la friolera de 240ms. ¿Por qué putImageData es tan lento en comparación con volver a dibujar el lienzo, aunque redibujar el lienzo implica rellenar casi todo el lienzo con drawImage y volver a llenar aproximadamente el 50% del lienzo con polígonos utilizando lineTo, trazo y relleno. Así que, básicamente, cada píxel se toca al menos una vez cuando se vuelve a dibujar.
Porque drawImage parece ser mucho más rápido que putImageData (después de todo, la parte de drawImage de redibujar el lienzo lleva menos de 30 ms). Decidí intentar guardar el estado del lienzo sin usar getImageData, sino utilizar canvas.toDataURL y luego crear una imagen a partir de la URL de datos que me quedaría en drawImage para dibujarla en el lienzo. Resulta que todo este procedimiento es mucho más rápido y solo toma aproximadamente 35ms para completarse.
Entonces, ¿por qué putImageData es mucho más lento que las alternativas (usando getDataURL o simplemente redibujando)? ¿Cómo podría acelerar las cosas más? ¿Existe y si, en general, es la mejor forma de almacenar el estado de un lienzo?
(Todas las cifras se miden utilizando Firebug desde Firefox)
Sería interesante si pudiera publicar una demostración de su problema en línea en alguna parte. En noVNC (http://github.com/kanaka/noVNC) utilizo putImageData para muchas matrices de datos de imágenes pequeñas y medianas y no veo un problema de rendimiento con putImageData. Tal vez te encuentres con un caso específico de rendimiento pésimo que debería ser solucionado. – kanaka
Puedes ver aquí http://www.danielbaulig.de/A3O/ No funcionará al 100% si la consola Firebug está activada, así que asegúrate de encenderla. La versión desprotegida es la que usa putImageData. Puede activarlo haciendo clic en cualquier "mosaico". Actualizará el lienzo de búfer utilizando putImageData y luego "resaltará" el mosaico seleccionado. En a3o_oo.js hay algunas líneas comentadas, que se pueden usar para alternar entre el uso de putImageData (actual), el uso de getDataURL (las dos líneas que mencionan this.boardBuffer) y el redibujado simple (la línea drawBoard) del lienzo del búfer. –
Gran pregunta y excelentes soluciones. ¿Pero alguna vez descubrió la verdadera razón por la cual putImageData es tan lento en comparación con drawImage? – cherouvim