4

The HTML5 Canvas has no method for explicitly setting a single pixel.

The solution I know so far is :

  • use getImageData and putImageData but the efficiency is too low for animation due to the low performance of putImageData

  • use heavy object like rect or putImageData to draw single pixel but the performance seems far worse when there is a lot of pixel to draw.

I have seen that the drawImage function is really faster than the putImageData and indeed if we replace putImageData by drawImage(new Image(w,h)), it is really fast. However i do not know any solution to put an image on argument of drawImage which can be set pixel by pixel fastly.

Her is an example of slow code

HTML:

<canvas id="graph1" width="1900" height="1000"></canvas>

Javascript:

    var canvas=document.getElementById("graph1"),
        ctx=canvas.getContext("2d"),
        imageData,
        data,
        w=canvas.width,
        loop=0,
        t=Date.now();

    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
          window.setTimeout(callback, 1000 / 60);
        };
      })();


    function animate() {
        imageData=ctx.createImageData(w, canvas.height);
        data=imageData.data;
        for(i=0;i<30000;i++) { // Loop fast enough
            x=Math.round(w*Math.random());
            y=Math.round(canvas.height*Math.random());   
            data[((w * y) + x) * 4]=255;
            data[((w * y) + x) * 4+1]=0;
            data[((w * y) + x) * 4+2]=0;
            data[((w * y) + x) * 4+3]=255;
        }
        ctx.putImageData(imageData, 0, 0); //Slow
        //ctx.drawImage(new Image(canvas.width, canvas.height),0,0);// Would be about 4x faster even if ImageData would be also blank

        requestAnimFrame(function() {
                loop++;
                if(loop<100)
                    animate();
                else
                    alert('finish:'+(Date.now()-t));
            });
    }
    animate();

If someone have a clue to improve performance.

Hentold
  • 853
  • 7
  • 11

1 Answers1

0

putImageData is what you will want to use, (if you are planning on html5 canvas). It is just as fast as drawImage.

If both drawImage and putImageData methods have similar images that they repaint, they end up being the same speed. You are comparing repainting speeds of completely random pixes, to repainting of blank over and over. If you need proof of this I can make an example.

Daniel Moses
  • 5,872
  • 26
  • 39
  • I am not sure of that at all. You can have a look at http://jsperf.com/buffering . `drawImage` is about 100x faster than `putImageData`. And on my sample replace the line `ctx.putImageData(...)` by the line `ctx.drawImage(...)` and you will see that the script is faster even for a blank image (only 4 times faster on this example but it will be nice enough to improve fluency of animation). It is indeed very strange by the way that the browsers are optimized for `drawImage` and not for `putImageData` – Hentold Jan 25 '13 at 11:11
  • http://jsfiddle.net/DEw3b/1/ It's interesting that this is equal on one of my computers but not on another. In any case, you can't do single pixels with draw. So it's sort of a not that important. – Daniel Moses Jan 27 '13 at 22:23