javascriptimagedata

javascript ImageData copy or move performance


I am writing a "waterfall" diagram for an SDR receiver which is displayed in a canvas on a web page.

The canvas has a size of w=1000 h=800 pixels. The top line is delivered every 50ms from a server. The browser (using javascript) must move all lines down one line and then insert the new line at the top. This gives the look of a waterfall where all pixels are moving from top to bottom.

It is working fine, but the CPU load for the pixel moving is very high, too high for i.e. a raspberry.

What I am doing is:

var imagedata = context.getImageData(0,0,pixwidth,height-1);
var dataCopy = new Uint8ClampedArray(imagedata.data);
for(i=(dataCopy.length - (2*pixwidth*4)); i>= 0; i--) {
    dataCopy[i+ pixwidth*4] = dataCopy[i];
}

imagedata.data.set(dataCopy);    
// insert new top line
// ....

context.putImageData(imagedata, 0, 0);

I also tried to directly copy the pixel data in imagedata[some index], which gives almost the same bad performance.

In another C-Program I did the same thing with a simple memcpy operation which is very fast. But what to do in Javascript ? There are 800.000 pixels, which are 3.200.000 bytes. How can I copy or move them with the best possible performance in Javascript ?


Solution

  • var cv = document.getElementById('cv');
    var ctx = cv.getContext('2d');
    
    function draw() {
        ctx.fillStyle = `hsla(${360 * Math.random()}, 100%, 50%, 1)`;
        ctx.fillRect(0, 0, cv.width, 10);
        ctx.drawImage(cv, 0, 10);
    }
    
    setInterval(function() { draw() }, 200)
    <canvas id="cv" width="800" height="400"></canvas>

    After drawing a line, take a snapshot of the entire canvas and redraw it with an offset of 10 px on the y scale. Repeat the process and you will get an waterfall like effect.