Es posible enviar un CanvasPixelArray obtenidos a través de la getImageData a un trabajador de la secuencia de comandos, y dejar que el trabajador de la secuencia de comandos de manipular los píxeles en su subproceso en segundo plano, y, finalmente, publicar la manipulados matriz de píxeles de la espalda.

Sin embargo, estoy usando el nativo de lona de las funciones de dibujo, como drawImage. El drawImage llamadas son actualmente bloquea el subproceso de interfaz de usuario. Esto hace que redibujar lento de botones, y un notable retraso al hacer clic en un botón, sólo para nombrar unos pocos inconvenientes. (Edit: Una pequeña mejora se pueden lograr ahora con ctx.imageSmoothingEnabled = false, al menos en WebKit con el webkit prefijo.)

Que me gustaría trasladar el dibujo desde el hilo principal en un subproceso en segundo plano el uso de los Web workers. Sin embargo, no parecen ser capaces de enviar a la lona ni el contexto para el trabajador.

Me hizo encontrar este aviso sobre MDN:

Nota: Como de costumbre, subprocesos en segundo plano—incluyendo a los trabajadores—no se puede manipular el DOM. Si las acciones tomadas por el subproceso de fondo necesidad de producir cambios en el DOM, deben publicar los mensajes de nuevo a sus creadores para hacer ese trabajo.

Pero me gustaría dejar el DOM tal como es; simplemente quiero dibujar cosas en un elemento canvas. Es esto posible, o en la Web los Trabajadores sólo se les permitió calcular y no se dibujar?

(O es tal vez posible utilizar funciones como drawImage para manipular un CanvasPixelArray en lugar de dibujar sobre un lienzo?)

InformationsquelleAutor pimvdb | 2011-11-17

4 Comentarios

  1. 12

    [comunidad edit: Esta respuesta fue escrita y aceptada en 2011. Otras tecnologías que han surgido (o emergentes) que pueden permitir la Web de los Trabajadores y de Lona para co-existir mejor; el lector debe ser consciente de todas las respuestas en esta página además de esta respuesta.]

    No se puede pasar un objeto de lienzo o lona de contexto a un subproceso de trabajo debido a que el lienzo es parte de la DOM.

    • Eso es una lástima. Por lo tanto, es correcto estoy básicamente obligados a utilizar el hilo principal de dibujo? Hay realmente ninguna manera de llamar a un CanvasPixelArray?
    • Yep. Incluso si usted tenía un equivalente de la API para drawImage() que funciona en un CanvasPixelArray, usted todavía necesita para enviar los datos para el subproceso de interfaz de usuario para el dibujo actual. Yo he oído hablar de un fuera de la pantalla de Lona para su uso en estas situaciones, pero es algo que tendrá que esperar en el navegador de los proveedores a implementar.
    • ¿No sería increíble si alguien implementado el lienzo de la API en javascript puro por lo que podríamos usar en la web de los trabajadores
    • Usted puede JSON.stringify la CanvasPixelArray, manipular en el trabajador, y cuando sale el resultado de la espalda, analizar el json, y el uso putImageData a poner el resultado en el lienzo
    • Hay una nueva API para ello (sólo compatible con Firefox si habilita un pref). Consulte developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas y hacks.mozilla.org/2016/01/webgl-off-the-main-thread.
    • Re «todavía necesita para enviar los datos para el subproceso de interfaz de usuario para el dibujo real»; Pero w sólo que, no lag de la interfaz de usuario ¿no?
    • Significado?
    • es bastante retraso teniendo en cuenta que usted puede solo post toda la cosa para un webworker.

  2. 36

    [Editar ~5 años más tarde: algo de esto está empezando a cambiar, y hay nueva web de la plataforma de características que permiten una representación de un lienzo de un Trabajador! Ver este blog para más info: https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/ – el resto de la respuesta proporcionada para el año 2011 de la era de la información ;)]

    Web de los trabajadores sólo se puede calcular, no modificar el DOM o hacer llamadas a dibujar en un lienzo. Sin embargo, como usted dice que usted puede enviar una matriz de píxeles para una web trabajador para el proceso allí y publicarlo de nuevo. Ya que es asincrónico, no veo por qué eso iba a causar ningún tipo de ralentización en el subproceso de interfaz de usuario, a menos que usted deliberadamente bloque hasta que la web trabajador responde (que no debería).

    Por lo que parece extraño que su drawImage llamadas están tomando tanto tiempo que está afectando a la interfaz de usuario. La mayoría de los lienzos son acelerados por hardware en estos días por lo que debería ir muy bien. Mi conjetura es que usted está dibujando a través de una web trabajador a un lienzo matriz de píxeles cada fotograma, que significa que usted es la representación de software en el lienzo en javascript. Javascript es todavía demasiado lento para hacer esto – incluso de software C++ representadores son una especie de lento, que es la razón por la aceleración de hardware es importante. Así que usted puede hacer algo un lienzo de matriz de píxeles en una web trabajador una vez, y luego cuando sale el resultado de la caché en un Image una vez y, a continuación, dibuje el Image a la lona como le gusta. Que todavía debe ser muy rápido.

    Editar: es posible que desee buscar en WebGL, donde se puede escribir fragment shaders que efectivamente son pequeños programas para procesar los efectos de píxel. Se ejecuta en su totalidad en la tarjeta gráfica por lo que están estúpidamente rápido.

    • De hecho no he implementado Web de los Trabajadores, sin embargo, que es la razón por la que es actualmente el bloqueo. WebGL parece muy interesante, se ve como todo un nuevo mundo de procesamiento y dibujo. Gracias por tu suggesions. (La aceleración de Hardware está, por alguna razón, mucho más lento en mi pc en Chrome de renderizado por software, con lo que la aceleración no es una posibilidad (aún)).
  3. 10

    Usted puede publicar el ImageData a la Web del Trabajador, que envía el manipulado ImageData de nuevo a la persona que llama (interfaz Principal) hilo.

    E. g.:

    1. Crear un Web Worker:

      este.representador = new Trabajador("renderer.js");
    2. Post el ImageData creado a partir de la lona a la Web del Trabajador:

      var ctx = este.el lienzo.getContext('2d'); 
      var imageData = ctx.createImageData(anchura, altura); 
      este.representador.postMessage({ imagen: imageData });
    3. Hacer ImageData manipulación en la Web del Trabajador y la posterior vuelta al hilo Principal:

      onmessage = function(e) { 
      var processedImage = auto.doImageProcessing(e.de datos.imagen); 
      postMessage({ imagen: processedImage }); 
      };

    4. Conjunto de la manipulados ImageData a la lona en el hilo Principal:

      este.representador.onmessage = function (e) { 
      var ctx = este.el lienzo.getContext('2d'); 
      ctx.putImageData(e.de datos.imagen, 0, 0); 
      }

    • Ahora sólo falta que alguien hace posible la creación de un CanvasRenderingContext2D para operar en el imageData en la web trabajador
    • Esto funciona, pero el rendimiento es bastante decepcionante.
    • Hice la prueba con [imageData] en el segundo argumento de postMessage?

Dejar respuesta

Please enter your comment!
Please enter your name here