JavaScript的ImageData复制或移动性能

4

我正在为网页上的画布编写一张SDR接收器的“瀑布”图。

画布大小为w = 1000 h = 800像素。 顶部行每50毫秒从服务器传送一次。 浏览器(使用JavaScript)必须将所有行向下移动一行,然后在顶部插入新行。这给人以瀑布的外观,其中所有像素都从上到下移动。

它能正常工作,但像素移动的CPU负载非常高,对于树莓派等设备来说太高了。

我正在做的是:

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);

我还尝试直接复制imagedata[some index]中的像素数据,但性能几乎相同。

在另一个C程序中,我用简单的memcpy操作做了同样的事情,这非常快。但在Javascript中该怎么办呢?有800,000个像素,共3,200,000字节。如何在Javascript中以最佳性能复制或移动它们?

1个回答

2

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>

绘制一条线后,拍摄整个画布的快照,并在y轴上偏移10像素重新绘制它。重复这个过程,你就会得到一个类似瀑布的效果。


只需 drawImage(cv,0,10) - Kaiido
谢谢,iacobalin,这看起来非常不错。但是你能解释一下为什么这些行会向下移动吗?你将矩形绘制到第10行,但是我在你的代码片段中看到旧行被向下移动了。 - harry4516
嗨,哈利,这里的10代表正在绘制的矩形的高度。将它们向下移动的是ctx.drawImage(cv, 0, 10),其中cv是当前在画布上可见的图像,在y轴上向下移动10个像素进行绘制。就像拍摄当前画布的照片,将其向下移动10个像素,插入新行等等。 - iacobalin
接受的答案!感谢您的解决方案,我能够将CPU负载从49%降低到3.3%,这是一个令人印象深刻的改进。 - harry4516

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接